Following Google's android data binding, I have been removing findViewById()
in my code.
I have a recycler view with click listener for each button in a particular item view. I am trying to find a way to eliminate the findViewById()
method in this particular case.
Code Snippet From MainFragment.java file:
// Add touch listener for the recycler view
mainFragmentBinding.mainFragmentFoodItemsRecyclerView.addOnItemTouchListener(
new RecyclerTouchListener(
getContext(),
mainFragmentBinding.mainFragmentFoodItemsRecyclerView,
new ClickListener() {
@Override
public void onClick(View view, final int position) {
Button addButton = view.findViewById(R.id.food_add_button);
addButton.setOnClickListener(addButtonView -> {
// Notify user
Toast.makeText(getContext(), "Clicked on Add button",
Toast.LENGTH_SHORT).show();
});
// Values are passing to activity & to fragment as well
Toast.makeText(
getContext(),
"Single Click on position : " + position,
Toast.LENGTH_SHORT
).show();
}
@Override
public void onLongClick(View view, int position) {
Toast.makeText(
getContext(),
"Long press on position : " + position,
Toast.LENGTH_LONG
).show();
}
}
));
The line I want to change from the above snippet:
Button addButton = view.findViewById(R.id.food_add_button);
Is this possible? If yes, can someone help me with the same?
Or should I leave the findViewById()
method as such?
Yeah, you can replace it, and you probably should.
To do so, first prepare your item layout for data-binding and add the click callback in there:
?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
<variable
name="item"
type="com.example.your.item.Type"/>
<variable
name="parentViewModel"
type="com.example.your.viewmodel.Type"/>
</data>
<YourLayout
...
android:onClick="@{() -> parentViewModel.onItemClicked(item)}"
...
YourLayout />
</layout>
In your view holder, declare a property to hold a reference to your item layout bindable:
lateinit var binding: YoutItemLayoutBindable
In your adapter, inside onCreateViewHolder(...)
, make sure you inflate your item layout using data-binding:
val inflater = LayoutInflater.from(parent.context)
val binding = DataBindingUtil.inflate<YoutItemLayoutBindable>(inflater, R.layout.your_item_layout, parent, false)
val viewHolder = ViewHolder(binding.root)
// Pass your activity/fragment as the lifeCycleOwner when creating the adapter
binding.lifecycleOwner = lifeCycleOwner
// Pass also your viewmodel as a parameter when creating the adapter
binding.parentViewModel = parentViewModel
viewHolder.binding = binding
return viewHolder
Then, inside onBindViewHolder(...)
, set the item as a variable for your binding:
val item = dataSet[position]
viewHolder.binding.item = item
viewHolder.binding.executePendingBindings()
And that's it! Your code might be different than this example (maybe you are not even using viewmodels), but I hope you can get the idea.