ListView异步加载图片 ListView异步加载图片

关于ListView异步加载图片有很多方式,也有很多方法可以解决图片错位的现象,看完他们写的代码,多半是基于回调的方式,比如这位: http://www.iteye.com/topic/685986
他解决错位的方式很巧妙:
ImageView imageViewByTag = (ImageView) listView.findViewWithTag(imageUrl);
在构造适配器是传入ListView的引用,由唯一的TAG来找显示的ImageView;
还有这位: http://www.iteye.com/topic/1118828
为了提升用户的体验效果,使用了线程等待。

下面分享我的方法:
也没有考虑到加载数量多的图片,和大图片,这些用户可以根据自己需要用ThumbnailUtils类进行处理,关于一次启动几十个线程的问题,我感觉没有担心的必要,感觉分页就可以解决。
下面贴代码(可以处理加载网络图片和本地图片):
Java代码 复制代码  收藏代码
  1. import java.io.IOException;   
  2. import java.io.InputStream;   
  3. import java.lang.ref.SoftReference;   
  4. import java.net.MalformedURLException;   
  5. import java.net.URL;   
  6. import java.util.HashMap;   
  7.   
  8. import android.graphics.Bitmap;   
  9. import android.graphics.BitmapFactory;   
  10. import android.os.Handler;   
  11. import android.os.Message;   
  12. import android.widget.ImageView;   
  13.   
  14. /**  
  15.  * 图片异步加载工具类  
  16.  *   
  17.  * @version V1.0  
  18.  */  
  19. public class AsynImageLoader {   
  20.   
  21.     // 图片软引用   
  22.     private HashMap<String, SoftReference<Bitmap>> imageCache;   
  23.     // 显示图片的ImageView   
  24.     private HashMap<String, ImageView> imageViews;   
  25.   
  26.     public AsynImageLoader() {// 构造   
  27.         imageCache = new HashMap<String, SoftReference<Bitmap>>();   
  28.         imageViews = new HashMap<String, ImageView>();   
  29.     }   
  30.   
  31.     /**  
  32.      * 从网络上获取图片  
  33.      *   
  34.      * @param imageView  
  35.      *            显示图片的ImageView  
  36.      * @param imageUrl  
  37.      *            图片的地址  
  38.      * @return 图片  
  39.      */  
  40.     public Bitmap loadDrawableFromNet(final ImageView imageView,   
  41.             final String imageUrl) {   
  42.         return loadDrawable(imageView, imageUrl, new LoadCallBack() {   
  43.             public Bitmap load(String uri) {   
  44.                 return loadImageFromNet(uri);   
  45.             }   
  46.         });   
  47.     }   
  48.   
  49.     /**  
  50.      * 从本地获取图片  
  51.      *   
  52.      * @param imageView  
  53.      *            显示图片的ImageView  
  54.      * @param imageUrl  
  55.      *            图片的路径  
  56.      * @return 图片  
  57.      */  
  58.     public Bitmap loadDrawableFromLocal(final ImageView imageView,   
  59.             final String imageUrl) {   
  60.         return loadDrawable(imageView, imageUrl, new LoadCallBack() {   
  61.             public Bitmap load(String uri) {   
  62.                 return loadImageFromLocal(uri);   
  63.             }   
  64.         });   
  65.     }   
  66.   
  67.     /**  
  68.      * 获取图片  
  69.      *   
  70.      * @param imageView  
  71.      *            显示图片的ImageView  
  72.      * @param imageUrl  
  73.      *            图片路径或网络地址  
  74.      * @param load  
  75.      *            回调方法 加载本地图片或者加载网络图片  
  76.      * @return  
  77.      */  
  78.     private Bitmap loadDrawable(final ImageView imageView,   
  79.             final String imageUrl, final LoadCallBack load) {   
  80.   
  81.         // 判断软引用里是否有图片   
  82.         if (imageCache.containsKey(imageUrl)) {   
  83.             SoftReference<Bitmap> softReference = imageCache.get(imageUrl);   
  84.             Bitmap bitmap = softReference.get();   
  85.             if (bitmap != null) {   
  86.                 return bitmap;// 有则返回   
  87.             }   
  88.         }   
  89.   
  90.         // 将为添加到图片显示集合的 ImageViwe 加入到集合   
  91.         if (!imageViews.containsKey(imageUrl)) {   
  92.             imageViews.put(imageUrl, imageView);   
  93.         }   
  94.   
  95.         final Handler handler = new Handler() {   
  96.             public void handleMessage(Message message) {   
  97.                 imageViews.get(imageUrl).setImageBitmap((Bitmap) message.obj);   
  98.             }   
  99.         };   
  100.   
  101.         //启动线程获取图片   
  102.         new Thread() {   
  103.             public void run() {   
  104.                 Bitmap bitmap = load.load(imageUrl);//执行回调   
  105.                 imageCache.put(imageUrl, new SoftReference<Bitmap>(bitmap));   
  106.                 Message message = handler.obtainMessage(0, bitmap);   
  107.                 handler.sendMessage(message);   
  108.             }   
  109.         }.start();   
  110.         return null;   
  111.     }   
  112.   
  113.     private interface LoadCallBack {   
  114.         public Bitmap load(String uri);   
  115.     }   
  116.   
  117.     /**  
  118.      * 从网络加载图片  
  119.      *   
  120.      * @param url  
  121.      * @return  
  122.      */  
  123.     public Bitmap loadImageFromNet(String url) {   
  124.         URL m;   
  125.         InputStream i = null;   
  126.         try {   
  127.             m = new URL(url);   
  128.             i = (InputStream) m.getContent();   
  129.         } catch (MalformedURLException e1) {   
  130.             e1.printStackTrace();   
  131.         } catch (IOException e) {   
  132.             e.printStackTrace();   
  133.         }   
  134.         return BitmapFactory.decodeStream(i);   
  135.     }   
  136.   
  137.     /**  
  138.      * 从本地加载图片  
  139.      *   
  140.      * @param path  
  141.      * @return  
  142.      */  
  143.     public Bitmap loadImageFromLocal(String path) {   
  144.         return BitmapFactory.decodeFile(path);   
  145.     }   
  146. }  
import java.io.IOException;
import java.io.InputStream;
import java.lang.ref.SoftReference;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Handler;
import android.os.Message;
import android.widget.ImageView;

/**
 * 图片异步加载工具类
 * 
 * @version V1.0
 */
public class AsynImageLoader {

	// 图片软引用
	private HashMap<String, SoftReference<Bitmap>> imageCache;
	// 显示图片的ImageView
	private HashMap<String, ImageView> imageViews;

	public AsynImageLoader() {// 构造
		imageCache = new HashMap<String, SoftReference<Bitmap>>();
		imageViews = new HashMap<String, ImageView>();
	}

	/**
	 * 从网络上获取图片
	 * 
	 * @param imageView
	 *            显示图片的ImageView
	 * @param imageUrl
	 *            图片的地址
	 * @return 图片
	 */
	public Bitmap loadDrawableFromNet(final ImageView imageView,
			final String imageUrl) {
		return loadDrawable(imageView, imageUrl, new LoadCallBack() {
			public Bitmap load(String uri) {
				return loadImageFromNet(uri);
			}
		});
	}

	/**
	 * 从本地获取图片
	 * 
	 * @param imageView
	 *            显示图片的ImageView
	 * @param imageUrl
	 *            图片的路径
	 * @return 图片
	 */
	public Bitmap loadDrawableFromLocal(final ImageView imageView,
			final String imageUrl) {
		return loadDrawable(imageView, imageUrl, new LoadCallBack() {
			public Bitmap load(String uri) {
				return loadImageFromLocal(uri);
			}
		});
	}

	/**
	 * 获取图片
	 * 
	 * @param imageView
	 *            显示图片的ImageView
	 * @param imageUrl
	 *            图片路径或网络地址
	 * @param load
	 *            回调方法 加载本地图片或者加载网络图片
	 * @return
	 */
	private Bitmap loadDrawable(final ImageView imageView,
			final String imageUrl, final LoadCallBack load) {

		// 判断软引用里是否有图片
		if (imageCache.containsKey(imageUrl)) {
			SoftReference<Bitmap> softReference = imageCache.get(imageUrl);
			Bitmap bitmap = softReference.get();
			if (bitmap != null) {
				return bitmap;// 有则返回
			}
		}

		// 将为添加到图片显示集合的 ImageViwe 加入到集合
		if (!imageViews.containsKey(imageUrl)) {
			imageViews.put(imageUrl, imageView);
		}

		final Handler handler = new Handler() {
			public void handleMessage(Message message) {
				imageViews.get(imageUrl).setImageBitmap((Bitmap) message.obj);
			}
		};

		//启动线程获取图片
		new Thread() {
			public void run() {
				Bitmap bitmap = load.load(imageUrl);//执行回调
				imageCache.put(imageUrl, new SoftReference<Bitmap>(bitmap));
				Message message = handler.obtainMessage(0, bitmap);
				handler.sendMessage(message);
			}
		}.start();
		return null;
	}

	private interface LoadCallBack {
		public Bitmap load(String uri);
	}

	/**
	 * 从网络加载图片
	 * 
	 * @param url
	 * @return
	 */
	public Bitmap loadImageFromNet(String url) {
		URL m;
		InputStream i = null;
		try {
			m = new URL(url);
			i = (InputStream) m.getContent();
		} catch (MalformedURLException e1) {
			e1.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return BitmapFactory.decodeStream(i);
	}

	/**
	 * 从本地加载图片
	 * 
	 * @param path
	 * @return
	 */
	public Bitmap loadImageFromLocal(String path) {
		return BitmapFactory.decodeFile(path);
	}
}


这个处理方式没有用到回调,没让ListView传入Adapter,没让Adapter里的代码显得那么臃肿,下面贴两行调用:
Java代码 复制代码  收藏代码
  1. Bitmap cachedImage = loader.loadDrawableFromNet(item.imageView,url);   
  2. item.setImageBitmap(cachedImage);  
Bitmap cachedImage = loader.loadDrawableFromNet(item.imageView,url);
item.setImageBitmap(cachedImage);


核心的思想就是在加载类里面做一个集合来存放显示的ImageView

--写码笔记,欢迎交流
关于ListView异步加载图片有很多方式,也有很多方法可以解决图片错位的现象,看完他们写的代码,多半是基于回调的方式,比如这位: http://www.iteye.com/topic/685986
他解决错位的方式很巧妙:
ImageView imageViewByTag = (ImageView) listView.findViewWithTag(imageUrl);
在构造适配器是传入ListView的引用,由唯一的TAG来找显示的ImageView;
还有这位: http://www.iteye.com/topic/1118828
为了提升用户的体验效果,使用了线程等待。

下面分享我的方法:
也没有考虑到加载数量多的图片,和大图片,这些用户可以根据自己需要用ThumbnailUtils类进行处理,关于一次启动几十个线程的问题,我感觉没有担心的必要,感觉分页就可以解决。
下面贴代码(可以处理加载网络图片和本地图片):
Java代码 复制代码  收藏代码
  1. import java.io.IOException;   
  2. import java.io.InputStream;   
  3. import java.lang.ref.SoftReference;   
  4. import java.net.MalformedURLException;   
  5. import java.net.URL;   
  6. import java.util.HashMap;   
  7.   
  8. import android.graphics.Bitmap;   
  9. import android.graphics.BitmapFactory;   
  10. import android.os.Handler;   
  11. import android.os.Message;   
  12. import android.widget.ImageView;   
  13.   
  14. /**  
  15.  * 图片异步加载工具类  
  16.  *   
  17.  * @version V1.0  
  18.  */  
  19. public class AsynImageLoader {   
  20.   
  21.     // 图片软引用   
  22.     private HashMap<String, SoftReference<Bitmap>> imageCache;   
  23.     // 显示图片的ImageView   
  24.     private HashMap<String, ImageView> imageViews;   
  25.   
  26.     public AsynImageLoader() {// 构造   
  27.         imageCache = new HashMap<String, SoftReference<Bitmap>>();   
  28.         imageViews = new HashMap<String, ImageView>();   
  29.     }   
  30.   
  31.     /**  
  32.      * 从网络上获取图片  
  33.      *   
  34.      * @param imageView  
  35.      *            显示图片的ImageView  
  36.      * @param imageUrl  
  37.      *            图片的地址  
  38.      * @return 图片  
  39.      */  
  40.     public Bitmap loadDrawableFromNet(final ImageView imageView,   
  41.             final String imageUrl) {   
  42.         return loadDrawable(imageView, imageUrl, new LoadCallBack() {   
  43.             public Bitmap load(String uri) {   
  44.                 return loadImageFromNet(uri);   
  45.             }   
  46.         });   
  47.     }   
  48.   
  49.     /**  
  50.      * 从本地获取图片  
  51.      *   
  52.      * @param imageView  
  53.      *            显示图片的ImageView  
  54.      * @param imageUrl  
  55.      *            图片的路径  
  56.      * @return 图片  
  57.      */  
  58.     public Bitmap loadDrawableFromLocal(final ImageView imageView,   
  59.             final String imageUrl) {   
  60.         return loadDrawable(imageView, imageUrl, new LoadCallBack() {   
  61.             public Bitmap load(String uri) {   
  62.                 return loadImageFromLocal(uri);   
  63.             }   
  64.         });   
  65.     }   
  66.   
  67.     /**  
  68.      * 获取图片  
  69.      *   
  70.      * @param imageView  
  71.      *            显示图片的ImageView  
  72.      * @param imageUrl  
  73.      *            图片路径或网络地址  
  74.      * @param load  
  75.      *            回调方法 加载本地图片或者加载网络图片  
  76.      * @return  
  77.      */  
  78.     private Bitmap loadDrawable(final ImageView imageView,   
  79.             final String imageUrl, final LoadCallBack load) {   
  80.   
  81.         // 判断软引用里是否有图片   
  82.         if (imageCache.containsKey(imageUrl)) {   
  83.             SoftReference<Bitmap> softReference = imageCache.get(imageUrl);   
  84.             Bitmap bitmap = softReference.get();   
  85.             if (bitmap != null) {   
  86.                 return bitmap;// 有则返回   
  87.             }   
  88.         }   
  89.   
  90.         // 将为添加到图片显示集合的 ImageViwe 加入到集合   
  91.         if (!imageViews.containsKey(imageUrl)) {   
  92.             imageViews.put(imageUrl, imageView);   
  93.         }   
  94.   
  95.         final Handler handler = new Handler() {   
  96.             public void handleMessage(Message message) {   
  97.                 imageViews.get(imageUrl).setImageBitmap((Bitmap) message.obj);   
  98.             }   
  99.         };   
  100.   
  101.         //启动线程获取图片   
  102.         new Thread() {   
  103.             public void run() {   
  104.                 Bitmap bitmap = load.load(imageUrl);//执行回调   
  105.                 imageCache.put(imageUrl, new SoftReference<Bitmap>(bitmap));   
  106.                 Message message = handler.obtainMessage(0, bitmap);   
  107.                 handler.sendMessage(message);   
  108.             }   
  109.         }.start();   
  110.         return null;   
  111.     }   
  112.   
  113.     private interface LoadCallBack {   
  114.         public Bitmap load(String uri);   
  115.     }   
  116.   
  117.     /**  
  118.      * 从网络加载图片  
  119.      *   
  120.      * @param url  
  121.      * @return  
  122.      */  
  123.     public Bitmap loadImageFromNet(String url) {   
  124.         URL m;   
  125.         InputStream i = null;   
  126.         try {   
  127.             m = new URL(url);   
  128.             i = (InputStream) m.getContent();   
  129.         } catch (MalformedURLException e1) {   
  130.             e1.printStackTrace();   
  131.         } catch (IOException e) {   
  132.             e.printStackTrace();   
  133.         }   
  134.         return BitmapFactory.decodeStream(i);   
  135.     }   
  136.   
  137.     /**  
  138.      * 从本地加载图片  
  139.      *   
  140.      * @param path  
  141.      * @return  
  142.      */  
  143.     public Bitmap loadImageFromLocal(String path) {   
  144.         return BitmapFactory.decodeFile(path);   
  145.     }   
  146. }  
import java.io.IOException;
import java.io.InputStream;
import java.lang.ref.SoftReference;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Handler;
import android.os.Message;
import android.widget.ImageView;

/**
 * 图片异步加载工具类
 * 
 * @version V1.0
 */
public class AsynImageLoader {

	// 图片软引用
	private HashMap<String, SoftReference<Bitmap>> imageCache;
	// 显示图片的ImageView
	private HashMap<String, ImageView> imageViews;

	public AsynImageLoader() {// 构造
		imageCache = new HashMap<String, SoftReference<Bitmap>>();
		imageViews = new HashMap<String, ImageView>();
	}

	/**
	 * 从网络上获取图片
	 * 
	 * @param imageView
	 *            显示图片的ImageView
	 * @param imageUrl
	 *            图片的地址
	 * @return 图片
	 */
	public Bitmap loadDrawableFromNet(final ImageView imageView,
			final String imageUrl) {
		return loadDrawable(imageView, imageUrl, new LoadCallBack() {
			public Bitmap load(String uri) {
				return loadImageFromNet(uri);
			}
		});
	}

	/**
	 * 从本地获取图片
	 * 
	 * @param imageView
	 *            显示图片的ImageView
	 * @param imageUrl
	 *            图片的路径
	 * @return 图片
	 */
	public Bitmap loadDrawableFromLocal(final ImageView imageView,
			final String imageUrl) {
		return loadDrawable(imageView, imageUrl, new LoadCallBack() {
			public Bitmap load(String uri) {
				return loadImageFromLocal(uri);
			}
		});
	}

	/**
	 * 获取图片
	 * 
	 * @param imageView
	 *            显示图片的ImageView
	 * @param imageUrl
	 *            图片路径或网络地址
	 * @param load
	 *            回调方法 加载本地图片或者加载网络图片
	 * @return
	 */
	private Bitmap loadDrawable(final ImageView imageView,
			final String imageUrl, final LoadCallBack load) {

		// 判断软引用里是否有图片
		if (imageCache.containsKey(imageUrl)) {
			SoftReference<Bitmap> softReference = imageCache.get(imageUrl);
			Bitmap bitmap = softReference.get();
			if (bitmap != null) {
				return bitmap;// 有则返回
			}
		}

		// 将为添加到图片显示集合的 ImageViwe 加入到集合
		if (!imageViews.containsKey(imageUrl)) {
			imageViews.put(imageUrl, imageView);
		}

		final Handler handler = new Handler() {
			public void handleMessage(Message message) {
				imageViews.get(imageUrl).setImageBitmap((Bitmap) message.obj);
			}
		};

		//启动线程获取图片
		new Thread() {
			public void run() {
				Bitmap bitmap = load.load(imageUrl);//执行回调
				imageCache.put(imageUrl, new SoftReference<Bitmap>(bitmap));
				Message message = handler.obtainMessage(0, bitmap);
				handler.sendMessage(message);
			}
		}.start();
		return null;
	}

	private interface LoadCallBack {
		public Bitmap load(String uri);
	}

	/**
	 * 从网络加载图片
	 * 
	 * @param url
	 * @return
	 */
	public Bitmap loadImageFromNet(String url) {
		URL m;
		InputStream i = null;
		try {
			m = new URL(url);
			i = (InputStream) m.getContent();
		} catch (MalformedURLException e1) {
			e1.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return BitmapFactory.decodeStream(i);
	}

	/**
	 * 从本地加载图片
	 * 
	 * @param path
	 * @return
	 */
	public Bitmap loadImageFromLocal(String path) {
		return BitmapFactory.decodeFile(path);
	}
}


这个处理方式没有用到回调,没让ListView传入Adapter,没让Adapter里的代码显得那么臃肿,下面贴两行调用:
Java代码 复制代码  收藏代码
  1. Bitmap cachedImage = loader.loadDrawableFromNet(item.imageView,url);   
  2. item.setImageBitmap(cachedImage);  
Bitmap cachedImage = loader.loadDrawableFromNet(item.imageView,url);
item.setImageBitmap(cachedImage);


核心的思想就是在加载类里面做一个集合来存放显示的ImageView

--写码笔记,欢迎交流

猜你喜欢

转载自zhouxuebao87.iteye.com/blog/1609750