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 View
s 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
Android M Camera Intent + Permission Bug
Ndk Resolution Outcome: Project Settings: Gradle Model Version=5.4.1, Ndk Version Is Unknown Error
Parse JSON Array Without Key in Android
How to Generate an Md5 Checksum for a File in Android
Android Studio, Suddenly Got Gpu Driver Issue When Running Emulator
Move Markers in Google Map V2 Android
Uploading a Large File in Multipart Using Okhttp
Android Keeps Caching My Intents Extras, How to Declare a Pending Intent That Keeps Fresh Extras
In Androidx.Fragment.App.Fragment,Setuservisiblehint()Is Deprecated,And Not Executed,Why
How to Make Circle Custom Progress Bar in Android
How to Set Multiple Alarms Using Alarm Manager in Android
Camera Activity Returning Null Android
Facebook - "Cannot Query Users by Their Username" Solution
Android - Setonclicklistener VS Onclicklistener VS View.Onclicklistener
Broadcastreceiver + Sms_Received
Appcompatv7 - V21 Navigation Drawer Not Showing Hamburger Icon