Nikhil Reddy
Nikhil Reddy

Reputation: 73

How to Call Interface method from Xml using Data Binding?

Here's my Fragment:

 public class Fragment_Cities extends Fragment implements Adapter_Cities.CitiesListener {
    
        private Adapter_Cities adapterCities;
        private FragmentCitiesBinding binding;
    
        @Override
        public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
            binding = FragmentCitiesBinding.inflate(inflater, container, false);
            return binding.getRoot();
        }
    
        @Override
        public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
            super.onViewCreated(view, savedInstanceState);
            binding.recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
            adapterCities = new Adapter_Cities(this);
            binding.recyclerView.setAdapter(adapterCities);

            ViewModel_Cities viewModelCities = new ViewModelProvider(this).get(ViewModel_Cities.class);
            viewModelCities.getLiveDataCities().observe(getViewLifecycleOwner(), model_cities ->
                    adapterCities.setAdapterData(model_cities));
        }
    
        @Override
        public void onCitySelected(Model_Cities city) {
            if (!alertDialog.isShowing()) alertDialog.show();
            new DialogFragment_Map().newInstance(city.getName(), city.getLatLon(), this).
                    show(requireActivity().getSupportFragmentManager(), null);
        }
    
    }

**

Here's my Adapter:

**

public class Adapter_Cities extends RecyclerView.Adapter<Adapter_Cities.MyViewHolder> implements Filterable {

    private List<Model_Cities> cityList, cityListFiltered;
    public CitiesListener citiesListener;

    public class MyViewHolder extends RecyclerView.ViewHolder {
        private final RowCityBinding rowCityBinding;

        public MyViewHolder(View itemView) {
            super(itemView);
            rowCityBinding = RowCityBinding.bind(itemView);
//            itemView.setOnClickListener(v -> recyclerViewItemClickListener.onCitySelected(cityListFiltered.get(getBindingAdapterPosition())));
        }
    }

    public Adapter_Cities(CitiesListener citiesListener) {
        this.citiesListener = citiesListener;
    }

    @NonNull
    @Override
    public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.row_city, parent, false);
        return new MyViewHolder(itemView);
    }

    @Override
    public void onBindViewHolder(Adapter_Cities.MyViewHolder holder, int position) {
        holder.rowCityBinding.setModel(cityListFiltered.get(position));
        holder.rowCityBinding.executePendingBindings();
    }

    public void setAdapterData(List<Model_Cities> cityList) {
        this.cityList = cityList;
        this.cityListFiltered = cityList;
        notifyDataSetChanged();
    }

    @Override
    public int getItemCount() {
        return cityListFiltered == null ? 0 : cityListFiltered.size();
    }

    public interface CitiesListener {
        void onCitySelected(Model_Cities city);
    }

}

**

Here's my XML Layout:

**

<data>

    <variable
        name="callback"
        type="com.base.assignment.adapters.Adapter_Cities.CitiesListener" />

    <variable
        name="model"
        type="com.base.assignment.models.Model_Cities" />
</data>

<androidx.cardview.widget.CardView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginStart="15dp"
    android:layout_marginTop="8dp"
    android:layout_marginEnd="15dp"
    android:background="@color/white"
    android:onClick="@{()->callback.onCitySelected(model)}">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:padding="10dp">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{model.title}"
            android:textColor="@color/black"
            android:textSize="15sp"
            android:textStyle="bold" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{model.subTitle}"
            android:textColor="@color/black"
            android:textSize="12sp" />

    </LinearLayout>
</androidx.cardview.widget.CardView>

**

Here's the result i got:

**

My actual requirement is when user clicks on RecyclerView Item, the app must show a DialogFragment which should be called by a Fragment. So, I'm trying to trigger onClick of RecyclerView layout through XML, and the action that should happen on clicking is -> The information of clicked item should be sent to Fragment with Model Object as it's parameter.

Whereas When I clicked on Recyclerview Item no action is been happening. No crashes, no information in logcat, no updates in App UI.

As DataBinding shows the Compile time errors, i am seeing the below errors: enter image description here

And right to it, i see the code details of the issue (as attached below): enter image description here

Upvotes: 0

Views: 625

Answers (1)

androidLearner
androidLearner

Reputation: 1702

For that set your listener interface for layout within onBindViewHolder().

 @Override
public void onBindViewHolder(Adapter_Cities.MyViewHolder holder, int position) {
    holder.rowCityBinding.setCallback(citiesListener);
    holder.rowCityBinding.setModel(cityListFiltered.get(position));
    holder.rowCityBinding.executePendingBindings();
}

Upvotes: 1

Related Questions