How to achieve the performance optimization of ListView loading _android

Source: Internet
Author: User

ListView is a very important component in Android development, which displays specific content in a list based on the length of the data, and the user is free to define ListView for each column, but when ListView has a lot of data to load, it takes up a lot of memory, affect performance, you need to populate and reuse view on demand to reduce the creation of objects.

The core of ListView loading is its adapter, in this paper, ListView load Performance optimization is to Adpter optimization, a total of four levels:

0, the most original loading

1. Using Convertview

2. Using Viewholder

3, to achieve local refresh

0, the most original loading

Here is the adapter, in order to look convenient, the ListView data is passed directly to the adapter in the constructor, the code is as follows:

Private class Adapteroptml extends Baseadapter {
private layoutinflater mlayoutinflater;
Private arraylist<integer> Mlistdata;
Public adapteroptml (context context, arraylist<integer> data) {
Mlayoutinflater = Layoutinflater.from ( context);
Mlistdata = data;
}
@Override public
int GetCount () {return
Mlistdata = = null?: Mlistdata.size ();
}
@Override public
Object getitem (int position) {return
Mlistdata = null?: Mlistdata.get (position);
}
@Override public
long getitemid (int position) {return
position;
}
@Override public
View getview (int position, view Convertview, ViewGroup parent) {
View viewroot = Mlayoutinflat Er.inflate (R.layout.listitem, parent, false);
if (viewroot!= null) {
TextView txt = (TextView) Viewroot.findviewbyid (r.id.listitem_txt);
Txt.settext (GetItem (position) + "");
}
Return Viewroot
}
}

First, the use of Convertview

Line 27th of the above code has been alerted in eclipse:

Unconditional layout inflation from view adapter:should use view Holder pattern (use Recycled view passed to this Metho D as the second parameter) for smoother scrolling

This means that a view that is moved out of the viewable area can be reused, and it has been passed in as the second parameter of GetView, so it is not necessary to inflate every time from XML.

The optimized code is as follows:

@Override public
View getview (int position, View Convertview, ViewGroup parent) {
if (Convertview = null) {
C Onvertview = Mlayoutinflater.inflate (R.layout.listitem, parent, false);
}
if (Convertview!= null) {
TextView txt = (TextView) Convertview.findviewbyid (r.id.listitem_txt);
Txt.setvisibility (view.visible);
Txt.settext (GetItem (position) + "");
}
return convertview;
}

The above code adds to the judgment that if the incoming convertview is not NULL, it is reused directly, otherwise it will be inflate from the XML.

According to the code above, if a phone screen can display up to 5 listitem at the same time, then the most need to inflate 5 times from the XML, than AdapterOptmL0 each listitem need inflate obviously more efficient.

Although the above usage improves efficiency, it creates a trap, and if you reuse convertview, you need to reset all the properties that the view may have been modified.

As an example:

If the TextView in the first view is set to invisible in the GetView, the first view is the visible region in the scrolling process and assumes it is reused as a parameter in the GetView of the tenth view

Then, in the tenth view of the GetView inside not only to SetText, but also to setvisibility, because this is reused view is currently in invisible State!

Ii. Use of Viewholder

From the warning in line 27th of AdapterOptmL0, we can also see that the compiler recommends a model called Viewholder, what is this, first look at the code:

Private class Adapteroptml extends Baseadapter {

Private Layoutinflater Mlayoutinflater;
Private arraylist<integer> Mlistdata;
Public adapteroptml (context context, arraylist<integer> data) {Mlayoutinflater = Layoutinflater.from (context);
Mlistdata = data; 
Private class Viewholder {public Viewholder (View viewroot) {txt = (TextView) Viewroot.findviewbyid (r.id.listitem_txt);
} public TextView txt; @Override public int GetCount () {return mlistdata = = null?: Mlistdata.size ();} @Override public Object getitem (int p Osition) {return mlistdata = = null?: Mlistdata.get (position);} @Override public long getitemid (int position) {return
Position  @Override public View getview (int position, View Convertview, ViewGroup parent) {if (Convertview = null) {Convertview
= Mlayoutinflater.inflate (R.layout.listitem, parent, false);
Viewholder holder = new Viewholder (Convertview);
Convertview.settag (holder); } if (Convertview!= null && convertview.gettag () instanceof Viewholder) {Viewholder holder = (viewholder) convErtview.gettag ();
Holder.txt.setVisibility (view.visible);
Holder.txt.setText (GetItem (position) + "");}
return convertview; }
}

As you can see from the code, this step of optimization is to use a class Viewholder to save all the found child controls in ListItem so that you don't have to run through time-consuming findviewbyid each time.

This step of optimization, the more complex the ListItem layout when the effect is more obvious.

Third, to achieve local refresh

OK, so far, ListView's generally needed optimizations have been done, and it's time to consider the optimization requirements in the actual usage scenario.

During the actual use of the ListView process, the ListView data is usually updated in the background, and then the Adatper notifydatasetchanged method is invoked to update the ListView UI.

Then the problem, in general, will only update the ListView one/several data, and call the Notifydatasetchanged method will be all visual range of ListItem are refreshed, this is unscientific!

Therefore, the further optimization of the space is that the local refresh ListView, words do not say more to see the code:

Private class AdapterOptmL3 extends Baseadapter {private Layoutinflater mlayoutinflater, private ListView Mlistview; pri
Vate arraylist<integer> Mlistdata; Public AdapterOptmL3 (context context, ListView ListView, arraylist<integer> data) {Mlayoutinflater =
Layoutinflater.from (context);
Mlistview = ListView;
Mlistdata = data; 
Private class Viewholder {public Viewholder (View viewroot) {txt = (TextView) Viewroot.findviewbyid (r.id.listitem_txt);
} public TextView txt;  @Override public int GetCount () {return mlistdata = = null 0:mlistdata.size ();} @Override public Object getitem (int Position) {return mlistdata = = null 0:mlistdata.get (position);} @Override public long getitemid (int position) {RET
Urn position;  @Override public View getview (int position, View Convertview, ViewGroup parent) {if (Convertview = null) {Convertview
= Mlayoutinflater.inflate (R.layout.listitem, parent, false);
Viewholder holder = new Viewholder (Convertview); Convertview.settag (HoldER); } if (Convertview!= null && convertview.gettag () instanceof Viewholder) {Updateview (Viewholder)
Convertview.gettag (), (Integer) GetItem (position));
return convertview; } public void Updateview (Viewholder holder, Integer data) {if (Holder!= null && data!= null) {Holder.txt.setVi
Sibility (view.visible);
Holder.txt.setText (Data + "");}
public void notifydatasetchanged (int position) {Final int firstvisiableposition = Mlistview.getfirstvisibleposition ();
Final int lastvisiableposition = Mlistview.getlastvisibleposition ();
Final int relativeposition = position-firstvisiableposition; if (position >= firstvisiableposition && position <= lastvisiableposition) {Updateview (Viewholder)
Mlistview.getchildat (relativeposition). Gettag (), (Integer) GetItem (position));  else {//not visible listitem do not need to refresh manually, and when visible, it will be automatically refreshed through GetView}}

The modified adapter adds a method public void notifydatasetchanged (int position) can update only the specified ListItem according to position.

Partial refresh of the external articles

In the local refresh data interface, you can actually do something else: ListView is rolling without refreshing.

The specific idea is that if you are currently scrolling, remember a pending task, and so ListView stop scrolling when the brush, so that does not cause scrolling when the refresh disorder. The code is as follows:

Private class Adapteroptmlplus extends Baseadapter implements onscrolllistener{private Layoutinflater mlayoutinflater;
Private ListView Mlistview;
Private arraylist<integer> Mlistdata;
private int mscrollstate = Scroll_state_idle;
Private list<runnable> mpendingnotify = new arraylist<runnable> (); Public Adapteroptmlplus (context context, ListView ListView, arraylist<integer> data) {Mlayoutinflater =
Layoutinflater.from (context);
Mlistview = ListView;
Mlistdata = data;
Mlistview.setonscrolllistener (this); 
Private class Viewholder {public Viewholder (View viewroot) {txt = (TextView) Viewroot.findviewbyid (r.id.listitem_txt);
} public TextView txt; @Override public int GetCount () {return mlistdata = = null?: Mlistdata.size ();} @Override public Object getitem (int p Osition) {return mlistdata = = null?: Mlistdata.get (position);} @Override public long getitemid (int position) {return
Position @Override public View getview (int position, View Convertview, VIewgroup parent) {if (Convertview = = null) {Convertview = Mlayoutinflater.inflate (R.layout.listitem, parent, false);
Viewholder holder = new Viewholder (Convertview);
Convertview.settag (holder); } if (Convertview!= null && convertview.gettag () instanceof Viewholder) {Updateview (Viewholder)
Convertview.gettag (), (Integer) GetItem (position));
return convertview; } public void Updateview (Viewholder holder, Integer data) {if (Holder!= null && data!= null) {Holder.txt.setVi
Sibility (view.visible);
Holder.txt.setText (Data + "");} public void notifydatasetchanged (final int position) {Final Runnable Runnable = new Runnable () {@Override public void Ru N () {final int firstvisiableposition = Mlistview.getfirstvisibleposition (); final int lastvisiableposition = MLISTVIEW.G
Etlastvisibleposition ();
Final int relativeposition = position-firstvisiableposition; if (position >= firstvisiableposition && position <= lastvisiableposition) {if (mscrollstate = SCRoll_state_idle) {//Not currently scrolling, refresh LOG.D immediately ("Snser", "notifydatasetchanged position=" + position + "Update Now"); Updateview (
Viewholder) Mlistview.getchildat (relativeposition). Gettag (), (Integer) GetItem (position)); else {synchronized (mpendingnotify) {//is currently scrolling, wait for scrolling to stop and refresh log.d ("Snser", "notifydatasetchanged position=" + position + "
Update Pending ");
Mpendingnotify.add (this); The ListItem in the {//not visible range does not need to be refreshed manually, and will be automatically refreshed by GetView when visible ("Snser", "notifydatasetchanged position=" + position + "
Update Skip ");
}
}
};
Runnable.run (); @Override public void onscrollstatechanged (Abslistview view, int scrollstate) {mscrollstate = scrollstate; if (mscrolls Tate = = Scroll_state_idle) {//scrolling stopped, refresh the listitem that need to be refreshed synchronized (mpendingnotify) {final iterator<runnable>
iter = Mpendingnotify.iterator ();
while (Iter.hasnext ()) {Iter.next (). run (); Iter.remove ();}}  @Override public void Onscroll (Abslistview view, int firstvisibleitem, int visibleitemcount, int totalitemcount) {}}

The above is the full description of how performance optimization for ListView loading is achieved, and I hope it will help.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.