What Is the Benefit of Viewholder Pattern in Android

What is the benefit of ViewHolder pattern in android?

Understand how listview recycling works

How ListView's recycling mechanism works

You cannot recycle a row that is presently in use. The above link explains how listview recycling mechanism works

So What is the benefit of using ViewHolder?

Quoting docs

Your code might call findViewById() frequently during the scrolling of ListView, which can slow down performance. Even when the Adapter returns an inflated view for recycling, you still need to look up the elements and update them. A way around repeated use of findViewById() is to use the "view holder" design pattern.

    public View getView(int position, View convertView, ViewGroup parent) { 
ViewHolder holder;

if (convertView == null) { // if convertView is null
convertView = mInflater.inflate(R.layout.mylayout,
parent, false);
holder = new ViewHolder();
// initialize views
convertView.setTag(holder); // set tag on view
} else {
holder = (ViewHolder) convertView.getTag();
// if not null get tag
// no need to initialize
}

//update views here
return convertView;
}

You missed the important part convertView.setTag(holder) and holder = (ViewHolder) ConvertView.getTag()

http://developer.android.com/training/improving-layouts/smooth-scrolling.html

Explain individual role of convertView and View Holder Pattern in ListView

  • convertView

it's a view that was previously inflated (when convertView==null) and was on the screen, but now have been scrolled out of the screen, so you can re-use it to display data from the view that will enter the screen soon.

improves performance by reducing view inflation (calls to inflater.inflate are expensive), reduces garbage collection, and reduces memory allocation.

  • view holder

keeps a direct reference to your view.

potentially improves performance because findViewById is a for-loop going around the view hierarchy that can potentially eat away quite precious time of the UI thread. This improvement might be small, but in a fast scrolling list, every nano-second counts to have a nice smoth 60fps.

why does the ViewHolder pattern work?

If you want the best explanation on how the ViewHolder works, check out Romain Guy's Google I/O 2009 talk in youtube , specially the first 15 minutes.

In short, the Adapter functions as a link between the underlying data and the ViewGroup. It will render as many Views as required to fill the screen. Upon scrolling or any other event that pushes a View is out of the screen, the Adapter will reuse that View, filled with the correct data, to be rendered at the screen.

The getView(int pos, View view, ViewGroup parent) method will use the right View at any time, regardless of your layout. I do not know the internals of this, but I'm sure you can browse the source code for any adapter (such as ArrayAdapter.java) if you're interested.

The ViewHolder just keeps a pointer to the Views as obtained by view.findViewById(int id). It is the Adapter responsibility to return the right data corresponding to any position.

Slides 11 to 13 of Romain's presentation will make it a lot more clear than anything I can write.

Android: ViewHolder pattern and different types of rows?

Yes, though it is far better to override getViewTypeCount() and getItemViewType() in your Adapter. That will teach Android's object pool to only hand you a row of the proper type back in getView().

Why in ViewHolder pattern should the ViewHolder class be static?

One benefit of using static inner class, is that the inner class can be accessed from static methods, without having an instance of the outer class.

If the inner class non-static:

class MyOuter {
private int x = 7;
public void makeInner() {
MyInner in = new MyInner();
in.seeOuter();
}
class MyInner {
public void seeOuter() {
System.out.println("Outer x is " + x);
}
}
}

public static void main(String[] args) {
MyOuter mo = new MyOuter();
MyOuter.MyInner inner = mo.new MyInner();
inner.seeOuter();
}

If the inner class is static:

class BigOuter {
static class Nest {void go() { System.out.println("hi"); } }
}

class Broom {
static class B2 {void goB2() { System.out.println("hi 2"); } }
public static void main(String[] args) {
BigOuter.Nest n = new BigOuter.Nest();
n.go();
B2 b2 = new B2();
b2.goB2();
}
}

Does RecyclerView have ANY benefits other than forcing developers to use the ViewHolder pattern?

In new project you definitely should use RecyclerView, it's a newer API. It helps you with animating items and it also has better semantics of updating data in adapters.

Also it decouples the recycling logic from layout logic by embracing the LayoutManager pattern. (And it also comes with few handy LayoutManager implementations out of the box)

But I wouldn't necessarily advice you to move your existing code from ListView to RecyclerView unless you are not benefiting from it - and for basic lists you are probably not.

Confused about ViewHolder pattern and convertView

perhaps view returned from getTag on a subsequent call is for a different list item, and returns the wrong view

Adapters use a RecycleBin. This class allows the ListView to only create as many row layouts as will fit on the screen, plus one or two for scrolling and pre-loading. So if you have a ListView with 1000 rows and a screen that only displays 7 rows, odds are the ListViiew will only have 8 unique Views.

Now to your question using my example above: only eight row layouts and 8 subsequent ViewHolders are ever created. When the users scrolls no new row layouts are ever created; only the content of the row layout changes. So getTag() will always have a valid ViewHolder that references the appropriate View(s).

(Does that help?)



Related Topics



Leave a reply



Submit