当前位置: 代码迷 >> Android >> android异步图片加载3之handler+线程池+消息队列模式+缓存
  详细解决方案

android异步图片加载3之handler+线程池+消息队列模式+缓存

热度:515   发布时间:2016-05-01 19:10:20.0
android异步图片加载三之handler+线程池+消息队列模式+缓存

假象现在有这样一个需求:

????? 一个微博客户端或者多媒体客户端需要从服务端拉取一些数据,该数据中包含了很多图片,如果不用异步加载方式,可能会使主线程阻塞导致ANR异常,但是异步加载后如果每次都通过网络去下载图片,性能上会差很多,而且也会浪费流量,导致用户的不满,故现在增加一个缓存用来存储图片,缓存中包含内存存储和sdcard存储。先从缓存中去,在缓存中先从内存中取出,如果内存中没有再从sdcard去,如果sdcard中存在则直接返回该图片资源并放入内存中,如果两者都没有则从网络上下载,下载后并放入sdcard中供下次使用,这样就节约了资源开销,下面是主要代码:

PicManager(用来处理图片的操作):

public class PicManager {	private Map<String,SoftReference<Bitmap>> imgCache ;	private Context ctx;		public PicManager(Map<String,SoftReference<Bitmap>> imgCache,Context ctx) {		this.ctx = ctx;		this.imgCache = imgCache;	}			/**	 * 从网络上下载	 * @param url	 * @return	 */	public Bitmap getBitMapFromUrl(String url) {		Bitmap bitmap = null;		URL u =null;		HttpURLConnection conn = null;		InputStream is = null;		try {			u = new URL(url);			conn = (HttpURLConnection)u.openConnection();			is = conn.getInputStream();			bitmap = BitmapFactory.decodeStream(is);		} catch (Exception e) {			e.printStackTrace();		}		return bitmap;	}		/**	 * 从文件中读取	 * @return	 * @throws Exception 	 */	private Bitmap getBitMapFromSDCard(String url) throws Exception {		Bitmap bitmap = null;		String filename = MD5Util.getMD5(url);		FileInputStream fis = ctx.openFileInput(filename);		bitmap = BitmapFactory.decodeStream(fis);		return bitmap;	}		/**	 * 从缓存中读取	 * @param url	 * @return	 * @throws Exception 	 */	public Bitmap getImgFromCache(String url) throws Exception {		Bitmap bitmap = null;		//从内存中读取		if(imgCache.containsKey(url)) {			synchronized (imgCache) {				SoftReference<Bitmap> bitmapReference = imgCache.get(url);				if(null != bitmapReference) {					bitmap = bitmapReference.get();				}			}		} else {//否则从文件中读取			bitmap = getBitMapFromSDCard(url);			//将图片保存进内存中			imgCache.put(url, new SoftReference<Bitmap>(bitmap));		}		return bitmap;	}		/**	 * 将图片写入sdcard中	 * @param bitmap	 * @param url	 * @throws Exception	 */	public void writePic2SDCard(Bitmap bitmap,String url) throws Exception {		String filename = MD5Util.getMD5(url);		FileOutputStream fos = ctx.openFileOutput(filename, ctx.MODE_APPEND);		byte[] bitmapByte = PictureUtil.bitmap2Byte(bitmap);		ByteArrayInputStream bis = new ByteArrayInputStream(bitmapByte);		int len = 0;		byte[] b = new byte[bis.available()];		while((len = bis.read(b)) != -1) {			fos.write(b, 0, len);		}		if(null != bis) {			bis.close();		}		if(null != fos) {			fos.close();		}	}}

?ImgLoader(用来加在图片):

public class ImgLoader {	private Map<String,SoftReference<Bitmap>> imgCache = new HashMap<String,SoftReference<Bitmap>>();	private Context ctx;		public ImgLoader(Context ctx) {		this.ctx = ctx;	}		private PicManager manager = new PicManager(imgCache,ctx);	private Handler handler = new Handler();			private ExecutorService threadPool = Executors.newFixedThreadPool(5);		public Bitmap loadImg(final String url,final ImgCallback callback) {				//先从缓存中读取图片资源		Bitmap bitmap = null;		try {			bitmap = manager.getImgFromCache(url);;						if(null == bitmap) {				//开启线程从网络上下载				threadPool.submit(new Runnable() {//submit方法确保下载是从线程池中的线程执行					@Override					public void run() {						final Bitmap bitmapFromUrl = manager.getBitMapFromUrl(url);						try {							manager.writePic2SDCard(bitmapFromUrl,url);						} catch (Exception e) {							e.printStackTrace();						}						handler.post(new Runnable() {							@Override							public void run() {								callback.refresh(bitmapFromUrl);							}						});					}				});			} else {							}		} catch (Exception e) {			e.printStackTrace();		}		return bitmap;	}	}

?ImgCallback callback是一个接口,用来刷新界面

public interface ImgCallback {		public void refresh(Bitmap bitmap);}

?

  相关解决方案