http://blog.csdn.net/soesa/article/details/7787922
假象现在有这样一个需求:
一个微博客户端或者多媒体客户端需要从服务端拉取一些数据,该数据中包含了很多图片,如果不用异步加载方式,可能会使主线程阻塞导致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);
- }