Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I use Android DataBinding in a listview and still use a ViewHolder pattern?

I have an Android activity that pulls its data from an observable list inside an adapter class.

My getView() method in my adapter class is:

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    if (inflater == null) {
        inflater = (LayoutInflater) parent.getContext()
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    }

    // Perform the binding
    ActivityTeamMessageListRowBinding binding = DataBindingUtil.inflate(inflater, R.layout.my_activity_list_row, parent, false);
    binding.setInfo(list.get(position));
    binding.executePendingBindings();

    // Return the bound view
    return binding.getRoot();
}

And this works great. However, I see the Android-warning unconditional layout inflation from view adapter on the ActivityTeamMessageListRowBinding binding ... line.

I have been researching ViewHolders to fix this issue, but I can't seem to figure out how to accomplish this and still use my data binding. And presumably, the longer the list, the worse performance I'd see without using a ViewHolder.

Does anyone know how to extend my getView(...) code to incorporate a view binder? I have a 3 TextViews and 1 ImageView in my my_activity_list_row.xml.

like image 466
Brett Avatar asked Nov 11 '16 22:11

Brett


People also ask

Can we use DataBinding and ViewBinding together?

Yep, we don't use <layout> ViewBinding, because on DataBinding we must add that layout tag to generate Binding class and it's different with ViewBinding which automatically generates all layout to Binding class.

When should I use DataBinding?

With data binding, a change to an element in a data set automatically updates in the bound data set. Data binding may be used for many reasons, such as to link an application's user interface (UI) and the data it displays, for data entry, reporting and in text box elements.

What is the benefit of ViewHolder pattern in Android?

The ViewHolder design pattern enables you to access each list item view without the need for the look up, saving valuable processor cycles. Specifically, it avoids frequent call of findViewById() during ListView scrolling, and that will make it smooth.


1 Answers

Try this:

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    if (inflater == null) {
        inflater = ((Activity) parent.getContext()).getLayoutInflater();
    }

    // Perform the binding

    ActivityTeamMessageListRowBinding binding = DataBindingUtil.getBinding(convertView);

    if (binding == null) {
        binding = DataBindingUtil.inflate(inflater, R.layout.my_activity_list_row, parent, false);
    }

    binding.setInfo(list.get(position));
    binding.executePendingBindings();

    // Return the bound view
    return binding.getRoot();
}

I haven't used data binding with ListView (I'll use RecyclerView), but off the cuff, this is what I'd try. Use breakpoints or logging to confirm that, when convertView is not null, that you get binding back from getBinding() more often than not (and perhaps all the time — I'm hazy on how data binding's caching works).

like image 180
CommonsWare Avatar answered Oct 21 '22 07:10

CommonsWare