(轉自:http://www.iteye.com/topic/1123524)
關於ListView異步加載圖片有很多方式,也有很多方法可以解決圖片錯位的現象,看完他們寫的代碼,多半是基於回調的方式,比如這位:http://www.iteye.com/topic/685986
他解決錯位的方式很巧妙:
ImageView imageViewByTag = (ImageView) listView.findViewWithTag(imageUrl);
在構造適配器是傳入ListView的引用,由唯一的TAG來找顯示的ImageView;
還有這位:http://www.iteye.com/topic/1118828
為了提升用戶的體驗效果,使用了線程等待。
下面分享我的方法:
也沒有考慮到加載數量多的圖片,和大圖片,這些用戶可以根據自己需要用ThumbnailUtils類進行處理,關於一次啟動幾十個線程的問題,我感覺沒有擔心的必要,感覺分頁就可以解決。
下面貼代碼(可以處理加載網絡圖片和本地圖片):
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里的代碼顯得那么臃腫,下面貼兩行調用:
核心的思想就是在加載類里面做一個集合來存放顯示的ImageView