背景:在上一篇中,主要介绍了内存缓存封装类和SD卡上临时文件缓存封装类,这一篇中,我们来封装一下 从网络获取图片的工具类及异步加载图片类
1、从网络获取图片的工具类:ImageHttpUtil.java
package com.ice.android.common.util.imagecache; import java.io.FilterInputStream; import java.io.IOException; import java.io.InputStream; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.HttpStatus; import org.apache.http.client.ClientProtocolException; import org.apache.http.client.methods.HttpGet; import org.apache.http.impl.client.DefaultHttpClient; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.util.Log; /** * 从网络获取图片工具类 * @author ice */ public class ImageHttpUtil { private static final String TAG = "ImageHttpUtil"; /** * 请求网络 根据图片url从网络上获取图片 * 这里使用 apache的 HttpClient请求网络 * @param mImageParams * @return */ public static Bitmap getImageData(String url){ HttpGet getRequest = new HttpGet(url); try { HttpResponse response = new DefaultHttpClient().execute(getRequest); int statusCode = response.getStatusLine().getStatusCode(); if(statusCode != HttpStatus.SC_OK){ Log.w(TAG, "Error: "+statusCode+" while retrieving bitmap from "+url); return null; } HttpEntity entity = response.getEntity(); if(entity != null){ InputStream inputStream = null; try { inputStream = entity.getContent(); /* return BitmapFactory.decodeStream(inputStream); // Bug on slow connections, fixed in future release. */ FlushedInputStream fis = new FlushedInputStream(inputStream); return BitmapFactory.decodeStream(fis); } catch (IllegalStateException e) { e.printStackTrace(); }finally{ if(inputStream != null){ inputStream.close(); } entity.consumeContent(); } } } catch (ClientProtocolException e) { getRequest.abort(); // 中断请求 Log.w(TAG, "Error: "+e.getMessage()+" while retrieving bitmap from "+url); e.printStackTrace(); } catch (IOException e) { getRequest.abort(); // 中断请求 Log.w(TAG, "I/O Error: "+e.getMessage()+" while retrieving bitmap from "+url); e.printStackTrace(); } return null; } /** * 继承 FilterInputStream <过滤的输入流> * 能过滤掉/跳过输入流中的某些字节 * @author ice * */ private static class FlushedInputStream extends FilterInputStream { public FlushedInputStream(InputStream inputStream) { super(inputStream); } /** * 重写 skip() 方法 * 跳过和丢弃此输入流中数据的 n个字节,完成输入流的字节过滤 */ @Override public long skip(long n) throws IOException { long totalBytesSkipped = 0L; while (totalBytesSkipped < n) { long bytesSkipped = in.skip(n - totalBytesSkipped); if (bytesSkipped == 0L) { int b = read(); if (b < 0) { break; // we reached EOF } else { bytesSkipped = 1; // we read one byte } } totalBytesSkipped += bytesSkipped; } return totalBytesSkipped; } } }
package com.ice.android.common.util.imagecache; import java.util.concurrent.Callable; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import android.graphics.Bitmap; import android.os.Handler; import android.os.Message; import android.util.Log; /** * 异步加载图片缓存 类 * 单例模式 * @author ice * */ public class AsynImageLoader { private static final String TAG = "AsynImageLoader"; /** 线程池数量 */ private static final int THREAD_NUM = 3; /** 线程池 */ private ExecutorService executorService; /** 内存缓存对象 */ private ImageMemCache memCache; /** sd卡 文件缓存对象 */ private ImageFileCache fileCache; private static AsynImageLoader instance; /** * 单例模式 * @param memCache * @param fileCache */ private AsynImageLoader() { executorService = Executors.newFixedThreadPool(THREAD_NUM); this.memCache = new ImageMemCache(); this.fileCache = new ImageFileCache(); } /** * 获取实例 * @return */ public static synchronized AsynImageLoader getInstance(){ if(instance == null){ instance = new AsynImageLoader(); } return instance; } /** * 加载图片数据 * @param mImageParams * @param mHandler */ public void loadImageData(ImageParams mImageParams,Handler mHandler){ executorService.submit(new ImgLoadTask(mImageParams,mHandler)); } /** * 从网络上获取图片数据,并将图片缓存到内存或是sdcard上 * @param imageParams * @return */ private Bitmap loadNetImage(ImageParams imageParams){ Bitmap imageData = ImageHttpUtil.getImageData(imageParams.getUrl().trim()); if(imageData != null){ memCache.addBitmapToCache(imageParams, imageData); fileCache.addBitmapToSdcard(imageParams, imageData); }else{ Log.d(TAG, "获取网络图片数据失败,url = "+imageParams.getUrl()); } return imageData; } /** * 从本地缓存中获取图片数据 * 获得一个图片的数据,从三个地方获取,首先是内存缓存,然后是文件(sdcard)缓存,最后从网络获取 * @param imageParams * @return */ public Bitmap loadCacheImage(ImageParams imageParams){ Bitmap imageData = null; // 从内存缓存中获取图片 imageData = memCache.getImageData(imageParams); if(imageData == null){ // 从文件(sdcard)缓存中获取图片 imageData = fileCache.getImageData(imageParams); } return imageData; } /** * 图片加载子线程任务 内部类 * @author ice * * java.util.concurrent.Callable 接口类似于 Runnable,两者都是为那些其实例可能被另一个线程执行的类设计的。 * 但是 Runnable 不会返回结果 * */ private class ImgLoadTask implements Callable<Void>{ private ImageParams imageParams; private Handler handler; public ImgLoadTask(ImageParams mImageParams, Handler mHandler) { this.imageParams = mImageParams; this.handler = mHandler; } @Override public Void call() throws Exception { Message msg = new Message(); msg.obj = loadNetImage(imageParams); if(msg.obj != null){ // 将加载得到的图片对象 通过Message承载发送给Handler处理 handler.sendMessage(msg); } return null; } } }
ok ! 到这里关于App应用开发中 有关图片缓存问题的代码已封装完毕!
小吕, 初转Android开发 算是Android新人,愿与大家共同学习!