Search code examples
androidandroid-databindingfindviewbyid

Can we replace findViewById() using android databinding in this particular scenario?


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?


Solution

  • 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.