Recently in doing Android-related development, the ListView has a picture dislocation problem, today checked a lot of people write some things, so recorded, is a deeper understanding of it.
The ListView is a very common control that can be extended to a wide variety of functions, and has many similarities with the GridView. Can store large amounts of data. And when we need more complex layouts, we usually use Simpleadapter, or inherit baseadapter to rewrite them.
If the inheritance of Arrayadapter,simpleadapter, because the parent class itself maintains a list, so when there is data update, try to use the adapter add, so that the value of GetCount () is guaranteed to return is correct.
One of the more important overriding functions involved in this is GetView.
There are three ways to implement the return of a view in GetView.
The first way:
The simplest and easiest to understand is that each view generates a new view through inflate to return
Public View GetView (int position, View Convertview, ViewGroup parent) { Layoutinflater inflater = Layoutinflater.from (context); View item = inflater.inflate (R.layout.list_item_icon_text, null); ((TextView) Item.findviewbyid (R.id.text)). SetText (Data[position]); ((ImageView) Item.findviewbyid (R.id.icon)). Setimagebitmap ( return item;}
This way, when the amount of data is small, the disadvantage is not obvious, but when a ListView has a large number of entries, this way is very wasteful. Because every time the item appears, disappears or updates, it needs to be inflate again. has caused a lot of memory consumption.
So what's the way to save money?
The second way:
Let's see what the GetView function is Conertview. After viewing the official documentation, we found:
if This view is non-anullThis thisnew This view are always in the right Type (see Adapter.getviewtypecount () and Adapter.getitemviewtype (int)).
Note:
Getviewtypecount () is used to return a type of item with Getitemviewtype when there are different kinds of items in the ListView, such as a split line, and then sit on a different
The original Converview is used to reuse the view. After finding other information. Find a more classic picture as follows:
This diagram clearly describes how the ListView reuses the View. The ListView requests all visible items separately through GetView. At this point the Converview is empty.
When the item1 slide out of the screen, item8 sliding out from below, and then call GetView, but at this time the Converview is no longer empty, but the last one to underline the item1 of the screen, at this time we only need to re-modify the item1 of the data, Without having to recreate a new view.
This saves memory.
Then we get the second way.
Public View getView (intifnullfalse& 1) = = 1? micon1:micon2); return Convertview;}
In this way, we find the text and ico that need to be modified by Converview, and then modify the data to return.
Some people will say, the above has not solved the problem of reuse, there is a third way?
So let's take a look at how the third way Google recommends is implemented.
Static class Viewholder {TextView text;imageview icon;}
This defines an internal static class,
PublicView GetView (intposition, View Convertview, ViewGroup parent) {Viewholder holder; if(Convertview = =NULL) {Convertview=Minflater.inflate (R.layout.list_item_icon_text, parent,false); Holder=NewViewholder (); Holder.text=(TextView) Convertview.findviewbyid (r.id.text); Holder.icon=(ImageView) Convertview.findviewbyid (R.id.icon); Convertview.settag (holder);} Else{Holder=(Viewholder) Convertview.gettag ();} Holder.text.setText (Data[position]); Holder.icon.setImageBitmap (Position& 1) = = 1?micon1:micon2);returnConvertview;}
The TextView and ImageView previously found through Findviewbyid are then placed in the Converivew object in Convertview.settag (holder) mode.
This way, when reusing Converview again, you don't have to use Findviewbyid again to find it, eliminating the overhead.
Finally, refer to a diagram of someone else to illustrate the performance of three different ways.
Having written so much, there is a small problem that needs to be addressed:
When we are loading images and other resources asynchronously, because the download speed is different, so the re-reuse of the view, may cause image confusion.
To give a simple example:
If the above item1 and item8 two pictures download speed different, item8 download relatively fast.
Then when the item1 screen, item8 appear, ITEM8 will show the download good pictures, then item1 also downloaded, so the download picture of the thread will item1 (that is, with ITEM8 shared view) set to item1 download good pictures.
So here we have to go to the mark, which view is currently displayed, So the simplest way is to give each Holder.icon set a tag (that is, the URL of the picture), when the background download the picture, the Holder.icon tag and URL, if different, it is not the view of the picture, then do not load.
Android ListView in GetView learning summary