Looking for a picture on the web, the root cause of the dislocation of the ListView asynchronous loading image is the reuse of Convertview and the asynchronous operation.
If you do not reuse convertview, there will be no dislocation, but there is no problem with reusing Convertview without an asynchronous operation.
Let me briefly analyze:
When Convertview is reused, the first screen shows 7 records, GetView is called 7 times, and 7 Convertview are created.
When Item1 the screen, Item8 into the screen, there is no new view instance created for ITEM8, ITEM8 multiplexing is
Item1 View If there is no problem with async, although ITEM8 and Item1 point to the same view, but slide to
ITEM8 when the ITEM8 data is brushed, then Item1 data and ITEM8 are the same, because they point to the same piece of memory,
But Item1 has rolled out of the screen you can't see. When the Item1 is visible again, the view Item1 the data.
But when there is an asynchronous download there is a problem, assuming that the Item1 picture download slow, Item8 picture download faster, you roll up
Make Item8 visible, then ITEM8 first show its own downloaded pictures Yes, but wait until the Item1 pictures are downloaded when you find
ITEM8 's pictures also became ITEM1 images, as they were reused for the same view. If the Item1 picture is downloaded more than
ITEM8 picture fast, Item1 first brush on their own downloaded pictures, then you slide down, Item8 pictures have not downloaded, ITEM8
will show Item1 pictures first, because they are the same fast memory, when Item8 their own pictures after downloading Item8 pictures and then brush
Your own, you slide up to make Item1 visible, Item1 pictures will be the same as ITEM8 pictures,
Because they point to the same piece of memory.
The simplest solution is to say it online, set a tag for ImageView, and preset a picture.
When Item1 than Item8 picture download faster, you roll down to make Item8 visible, then ImageView's tag was set to
Item8 URL, when Item1 download finished, because ITEM1 is not visible now the tag is ITEM8 URL, so does not meet the conditions,
Although downloaded but not set to ImageView, tag is always identified as the URL of the picture in the visible view.
The key code is as follows:
Public View GetView (int position, View Convertview, ViewGroup parent) {Viewholder holder = null; if (Convertview = = null) {holder = new Viewholder (); Convertview = Layoutinflater.from (context). Inflate (R.layout.list_item, NULL); Holder.img = (ImageView) Convertview.findviewbyid (r.id.userimage); Convertview.settag (holder); } else {holder = (Viewholder) convertview.gettag (); } User user = List.get (position); Set a tag Holder.img.setTag (User.getimgurl ()) for ImageView; Preset a picture holder.img.setImageResource (R.drawable.ic_launcher); Final String Tmpimageurl = User.getimgurl (); if (user.getimgurl () = null &&!user.getimgurl (). Equals ("")) {Bitmap Bitmap = imageloader.loadimage (Holde R.img, User.getimgurl (), new Imagedownloadcallback () {@Override Publ IC void onimagedownloaded (ImageView ImageView, Bitmap Bitmap) { Prevent picture dislocation by tag if (Imageview.gettag ()! = NULL && Imageview.gettag (). Equals (Tmpimageurl)) {imageview.setimagebitmap (bitmap); } } }); if (bitmap! = null) {Holder.img.setImageBitmap (bitmap); }} return Convertview;}
I have a reference to the online data write a ListView asynchronous loading of the picture DEMO:
(1) using the thread pool
There is no thread pool, when the picture is very much, fast sliding the listview because each picture is opened by downloading a thread,
An OOM (out of memory) may occur.
(2) memory, file double cache
SoftReference soft references are also used here
/** * Picture Asynchronous Load Class * * @author Leslie.fang * @company enwaysoft * */public class Asyncimageloader {//MAX thread number private St atic Final int max_thread_num = 10; Private map<string, softreference<bitmap>> imagecaches = null; Private Fileutil Fileutil; Thread pool private Executorservice threadpools = null; Public Asyncimageloader (Context context) {imagecaches = new hashmap<string, softreference<bitmap>> (); Fileutil = new Fileutil (context); Public Bitmap LoadImage (final ImageView ImageView, final String imageUrl, final imagedownloadcallback imag Edownloadcallback) {final String filename = imageUrl. substring (Imageurl.lastindexof ("/") + 1); Final String filepath = Fileutil.getabsolutepath () + "/" + filename; First, look for the IF (Imagecaches.containskey (IMAGEURL)) {softreference<bitmap> reference = Imagecaches from the soft reference. Get (IMAGEURL); Bitmap Bitmap = Reference.get (); The Bitmap object in a soft reference may be recycled at any time//if the Bitmap in the soft reference has been reclaimed, look for an if (Bitmap! = null) from the file { LOG.I ("AAAA", "cache exists" + filename); return bitmap; }//Find if (fileutil.isbitmapexists (filename)) {log.i ("aaaa", "file exists" + filen) from the file AME); Bitmap Bitmap = Bitmapfactory.decodefile (filepath); Rejoin the memory soft reference in Imagecaches.put (IMAGEURL, New softreference<bitmap> (Bitmap)); return bitmap; }//Soft references and files are no longer downloaded from the network if (IMAGEURL! = null &&!imageurl.equals ("")) {if (Threadpools = = NULL) {Threadpools = Executors.newfixedthreadpool (max_thread_num); } final Handler Handler = new Handler () {@Override public void Handlemessage (Mes Sage msg) {if (Msg.what = = 111 && Imagedownloadcallback! = null) {BITM AP BItmap = (Bitmap) msg.obj; Imagedownloadcallback.onimagedownloaded (ImageView, bitmap); } } }; Thread thread = new Thread () {@Override public void run () {log.i ("AAAA" , Thread.CurrentThread (). GetName () + "is running"); InputStream InputStream = Httpservice.getinstance (). GetStream (IMAGEURL); Bitmap Bitmap = Bitmapfactory.decodestream (InputStream); Image download successfully re-caches and executes callback flush interface if (bitmap! = null) {//Add to soft reference in I Magecaches.put (IMAGEURL, New softreference<bitmap> (Bitmap)); Cache to File system Fileutil.savebitmap (filepath, bitmap); Message msg = new Message (); Msg.what = 111; Msg.obj = bitmap; Handler.sendmessage (msg); } } }; Threadpools.execute (thread); } return null; } public void Shutdownthreadpool () {if (threadpools! = null) {Threadpools.shutdown (); Threadpools = null; }}/** * Image download Complete Callback interface * */public interface Imagedownloadcallback {void onimagedownloaded (Ima Geview ImageView, Bitmap Bitmap); }}
The second explanation:
Today, when I do a picture asynchronous loading, a loaded picture does not match the actual location and the flashing load occurs. It turns out that the first common element in the ListView and the first visible element after sliding are shared by a convertview, resulting in the repeated use of Convertview at asynchronous loading, the workaround is to set the URL content for each ImageView control as the tag tag, Then compare the tag of the control to the incoming URL before you update the ImageView control
Determine whether the ImageView control is the control we want to set in the method of completing the asynchronous task
Blog reproduced from:
Http://www.cnblogs.com/lesliefang/p/3619223.html
http://blog.csdn.net/fanjunjian1991/article/details/8742748