Advanced Android--adapter in-depth understanding and optimization
typically for a multiple-element-containing View , such as ListView , GridView , Expandablelistview , the time we were to set it to a Adapter . Adapter is a bridge that provides data to and from view, and is also a view bridge that provides each Item .
in ListView as an example, it works as :
● ListView for List in each Item , Adapter will call a GetView method to get a layout view
● we will generally Inflate a new View , populates the data and returns the display
Of course, if our Item A lot of words (like tens of thousands) will create a new View it? Obviously this memory is not acceptable,Google will not do so,Android has a component called recycler , That's how he works:
Obviously, no matter how many item is in the data, recycler only stores the view in memory that is visible on the display. When you swipe down, the top invisible item moves directly back to the bottom to fill the data again into the new item. This way, you don't have to create a new view every time.
This is the invocation of the GetView method that we have common in adapter, and we can see that Convertview is the layout view of each item before Recyler.
Public View GetView (int position, view Convertview, viewgroupparent)
So, Android has provided us with a recycler mechanism, we should use this mechanism, not every time Inflate a View .
Example
Don ' t
Public View GetView (int position, view Convertview, viewgroupparent) { Convertview = Layoutinflater.from (Mcontext). Inflate (r.layout.item_view,null); dosomething ... return Converview;}
Do
Public View GetView (int position, View Convertview, viewgroupparent) { if (Convertview ==null) { Convertview = Layoutinflater.from (Mcontext). Inflate (R.layout.item_view, null); } dosomething ... return Converview;}
The role of Viewholder
The recycler model mentioned earlier is to solve the waste of view resources caused by repetitive inflate, and what methods can we optimize our performance again? The answer is yes.
We still from the GetView in each method call to see, we found that in fact, when we get convertview, each time will be based on this layout to Findviewbyid. As below, make our usual notation:
if (Convertview = = null) { Convertview = minflater.inflate (R.layout.item_view, null); } TextView Titletextview = (TextView) Convertview.findviewbyid (R.id.text)); ImageView Iconimageview = (ImageView) convertview.findviewbutid (R.id.icon)); DoSomething ...
Findviewbyid is in the analysis of the Layout.xml layout of the sub-view, parsing XML is a definitely work, so Google also suggested that we optimize the thankless of the work, so put forward the concept of viewholder.
that is, using a static class, save The reference relationship for each child View in the XML , so that you do not have to parse the XML every time up. As follows: A viewholder written for the code above
Static class Viewholder { TextView titletextview;
However, in the getview We can only get three parameters in the method, position , convertview , viewgroup is not getting our custom viewholder convertview get viewholder tag
The following is a complete Viewholder Use exmaple:
Public View GetView (int position, View Convertview, ViewGroup parent) { Viewholder holder; if (Convertview = = null) { Convertview = minflater.inflate (R.layout.item_view, null); Holder = new Viewholder (); Holder.titletextview = (TextView) Convertview.findviewbyid (r.id.text); Holder.iconimageview = (ImageView) Convertview.findviewbyid (R.id.icon); Convertview.settag (holder); } else { holder = (viewholder) convertview.gettag (); } Holder.titleTextView.setText (data[pos].title); Holder.iconImageView.setImageBitmap (DATA[POS].BITMAP); return convertview; } Static class Viewholder { TextView titletextview; ImageView Iconimageview; }
Tips. Support.v7 in the Recyclerview is the use of this idea to make.
Multiple types of ViewType
When we call method GetView in adapter, if the item view in the entire list has multiple types of layouts, such as:
We continue to use Convertview to populate the data as if it were not possible, because each returned Convertview type is different and cannot be reused.
This is what Android is thinking about when it comes to design. Therefore, the two methods reserved in the adapter.
public int Getitemviewtype (int position);
public int getviewtypecount ();
Only need to re-two methods, set the number of Itemviewtype and judgment method, recycler can selectively give different convertview.
Example:
@Override public intgetitemviewtype (int position) {if (Data[pos].type = = 0) {return 0; } else {return 1; }} @Override public int getviewtypecount () {return 2; } @Override public View getView (int position, view Convertview, ViewGroup arg2) {Titleviewholder titleholder ; Infoviewholder Infoholder; int type = Getitemviewtype (position); if (Convertview = = null) {switch (type) {Case 0:convertview = minflater.inflate (R). Layout.item_view, NULL); Titleholder = new Titleviewholder (); Titleholder.titletextview = (TextView) Convertview.findviewbyid (R.id.text); Titleholder.iconimageview = (ImageView) Convertview.findviewbyid (R.id.icon); Convertview.settag (titleholder); Break Case 1:convertview = minflater.inflate (r.layout.item_view2, NULL); Infoholder = new Infoviewholder (); Infoholder.titletextview = (TextView) Convertview.findviewbyid (R.id.text); Convertview.settag (Infoholder); Break }} else {switch (type) {case 0:titleholder = (titleviewholder) convertview . Gettag (); Break Case 1:infoholder = (infoviewholder) convertview.gettag (); Break }} switch (type) {case 0:titleholder.titletextview.settext (data[pos].title); Break Case 1:infoholder.titletextview.settext (Data[pos].title); InfoHolder.iconImageView.setImageBitmap (DATA[POS].BITMAP); Break } return Convertview; } static class Titleviewholder {public ImageView iconimageview; Public TextView Titletextview; } static class Infoviewholder {TextView titletextview; ImageView Iconimageview; }
notifydatasetchanged Refresh mechanism
When the data in the ListView changes and we want to refresh the view in the ListView, we typically call notifydatasetchanged to refresh the ListView. Take a look at its source code:
public void notifychanged () { synchronized (mobservers) { //sends a onchanged for (int i =) to each child view Mobservers.size ()-1; I >= 0; i--) { mobservers.get (i). onChanged ();}} }
It was found to be refreshed for every sub-view, of course, if our data variables were understandable. However, under general conditions, we need to update the view not much. Frequent calls to the notifydatasetchanged method are not appropriate for refreshing the entire interface. This will redraw all items displayed on the interface Once, even if only one view has changed.
So, we can write an update method to refresh a view individually
private void Updateview (int itemIndex) { intvisibleposition = yourlistview.getfirstvisibleposition (); VIEWV = Yourlistview.getchildat (itemindex-visibleposition); Viewholder Viewholder = (viewholder) v.gettag (); if (viewholder!= null) { ViewHolder.titleTextView.setText ("I updated");} }
Network picture optimization in adapter
Each item in the ListView has a network image, and when item is more, too many Web requests and too many image stores will be the ListView variable card.
So do the optimization for it:
Using the thread pool for network picture requests, network picture requests are obtained using local cache processing (LRUCache), memory + local file cache. Of course, a weak reference (WeakReference) is required to store the in-memory image in order to prevent memory overflow from being recycled.
Proportionally scales the pictures taken in the network to reduce memory consumption.
When you swipe, you don't need to request a Web image. Because, the network request is generally more time-consuming, an item of the picture, in the request when the recycler replaced, the picture will not correspond to the item.
Tips. The network request of the tool class is more inconvenient to cite examples, but the use of more frequent network Image request Tool class is volley, volley provides a Imageloader tool class and Networkimageview network picture request view
/**
* @author Zhoushengtao (Zhou San)
* @since July 8, 2014 15:08:29
* @weixin stchou_zst
* @blog http://blog.csdn.net/yzzst
*/