论坛首页 移动开发技术论坛

ListView异步加载图片

浏览 3908 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2012-05-09  
关于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里的代码显得那么臃肿,下面贴两行调用:
Bitmap cachedImage = loader.loadDrawableFromNet(item.imageView,url);
item.setImageBitmap(cachedImage);


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

--写码笔记,欢迎交流
论坛首页 移动开发技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics