图片文字缓存(下)图片缓存

来源:互联网 发布:mac pr防抖cc2017 编辑:程序博客网 时间:2024/04/29 14:42

<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">今天给大家带来的是关于图片的缓存</span>

简单介绍一下图片缓存,下面是图片缓存的一些代码以及我们怎么用

ImageCache 是一个工具类里面也有详细注解大家可以简单了解一下

package com.zhongwang.diebao.utils;import java.io.File;import java.util.Iterator;import java.util.LinkedList;import java.util.Locale;import java.util.Queue;import java.util.Stack;import org.apache.http.HttpEntity;import org.apache.http.HttpResponse;import org.apache.http.client.methods.HttpGet;import org.apache.http.util.EntityUtils;import android.annotation.SuppressLint;import android.app.ActivityManager;import android.content.Context;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.graphics.drawable.BitmapDrawable;import android.graphics.drawable.ColorDrawable;import android.graphics.drawable.Drawable;import android.graphics.drawable.TransitionDrawable;import android.media.ThumbnailUtils;import android.os.Handler;import android.os.HandlerThread;import android.os.Looper;import android.os.Message;import android.support.v4.util.LruCache;import android.util.Log;import android.widget.ImageView;import com.zhongwang.diebao.base.MyBaseApplication;/** * 图片加载类:双缓存+异步加载(内存及硬盘缓存+异步加载) */public class ImageCache {static final String TAG = ImageCache.class.getSimpleName();private static ImageCache mImageCache;public LruCache<String, Bitmap> mMemoryCache; // 内存缓存private static final int DISK_CACHE_SIZE = 1024 * 1024 * 20; // 10MBprivate static final String DISK_CACHE_SUBDIR = "thumbnails";public static DiskLruCache mDiskCache; // 硬盘缓存/** 图片加载队列,后进先出 */private Stack<ImageRef> mImageQueue = new Stack<ImageRef>();/** 图片请求队列,先进先出,用于存放已发送的请求。 */private Queue<ImageRef> mRequestQueue = new LinkedList<ImageRef>();/** 图片加载线程消息处理器 */private Handler mImageLoaderHandler;/** 图片加载线程是否就绪 */private boolean mImageLoaderIdle = true;/** 请求图片 */private static final int MSG_REQUEST = 1;/** 图片加载完成 */private static final int MSG_REPLY = 2;/** 中止图片加载线程 */private static final int MSG_STOP = 3;/** 如果图片是从网络加载,则应用渐显动画,如果从缓存读出则不应用动画 */private boolean isFromNet = true;/** * 获取单例,只能在UI线程中使用。 *  * @param context * @return */public static ImageCache getInstance(Context context) {// 如果不在ui线程中,则抛出异常if (Looper.myLooper() != Looper.getMainLooper()) {throw new RuntimeException("Cannot instantiate outside UI thread.");}if (mImageCache == null) {mImageCache = new ImageCache(context);}return mImageCache;}/** *  * @Title: clearCache  * @Description: 清理缓存 * @param  设定文件  * @return void 返回类型  * @throws */public static void clearCache(){mDiskCache.clearCache();}/** * 私有构造函数,保证单例模式 *  * @param context */private ImageCache(Context context) {int memClass = ((ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE)).getMemoryClass();memClass = memClass > 32 ? 32 : memClass;// 使用可用内存的1/8作为图片缓存final int cacheSize = 1024 * 1024 * memClass / 8;mMemoryCache = new LruCache<String, Bitmap>(cacheSize) {protected int sizeOf(String key, Bitmap bitmap) {return bitmap.getRowBytes() * bitmap.getHeight();}};File cacheDir = DiskLruCache.getDiskCacheDir(context, DISK_CACHE_SUBDIR);mDiskCache = DiskLruCache.openCache(context, cacheDir, DISK_CACHE_SIZE);}/** * 存放图片信息 */class ImageRef {/** 图片对应ImageView控件 */ImageView imageView;/** 图片URL地址 */String url;/** 图片缓存路径 */String filePath;/** 默认图资源ID */int resId;int width = 0;int height = 0;/** * 构造函数 *  * @param imageView * @param url * @param resId * @param filePath */ImageRef(ImageView imageView, String url, String filePath, int resId) {this.imageView = imageView;this.url = url;this.filePath = filePath;this.resId = resId;}ImageRef(ImageView imageView, String url, String filePath, int resId,int width, int height) {this.imageView = imageView;this.url = url;this.filePath = filePath;this.resId = resId;this.width = width;this.height = height;}}/** * 显示图片 *  * @param imageView *            要放在哪个ImageView中 * @param url * @param resId */public void displayImage(ImageView imageView, String url, int resId) {if (imageView == null) {return;}if (imageView.getTag() != null&& imageView.getTag().toString().equals(url)) {return;}if (resId >= 0) {if (imageView.getBackground() == null) {imageView.setBackgroundResource(resId);}// ???imageView.setImageDrawable(null);}if (url == null || url.equals("")) {return;}// 添加url tagimageView.setTag(url);// 读取map缓存Bitmap bitmap = mMemoryCache.get(url);if (bitmap != null) {setImageBitmap(imageView, bitmap, false);return;}// 生成文件名String filePath = urlToFilePath(url);if (filePath == null) {return;}queueImage(new ImageRef(imageView, url, filePath, resId));}/** * 显示图片固定大小图片的缩略图,一般用于显示列表的图片,可以大大减小内存使用 *  * @param imageView *            加载图片的控件 * @param url *            加载地址 * @param resId *            默认图片资源ID * @param width *            指定宽度 * @param height *            指定高度 */public void displayImage(ImageView imageView, String url, int resId,int width, int height) {Log.i("TAG", "displayImage--->");if (imageView == null) {return;}if (resId >= 0) {if (imageView.getBackground() == null) {imageView.setBackgroundResource(resId);}imageView.setImageDrawable(null);}if (url == null || url.equals("")) {return;             }// 添加url tagimageView.setTag(url);// 读取map缓存Bitmap bitmap = mMemoryCache.get(url + width + height);if (bitmap != null) {setImageBitmap(imageView, bitmap, false);return;}// 生成文件名String filePath = urlToFilePath(url);Log.i("TAG", "filePath--->"+filePath);if (filePath == null) {return;}queueImage(new ImageRef(imageView, url, filePath, resId, width, height));}/** * 入队,后进先出 *  * @param imageRef */public void queueImage(ImageRef imageRef) {// 删除已有ImageViewIterator<ImageRef> iterator = mImageQueue.iterator();while (iterator.hasNext()) {if (iterator.next().imageView == imageRef.imageView) {iterator.remove();}}// 添加请求mImageQueue.push(imageRef);sendRequest();}/** * 发送请求 */private void sendRequest() {// 开启图片加载线程if (mImageLoaderHandler == null) {// HandlerThread继承自Thread,当线程开启时,也就是它run方法运行起来后,// 线程同时创建了一个含有消息队列的Looper,并对外提供自己这个Looper对象的get方法,// 这就是它和普通Thread唯一不同的地方。HandlerThread imageLoader = new HandlerThread("image_loader");imageLoader.start();mImageLoaderHandler = new ImageLoaderHandler(imageLoader.getLooper());}// 发送请求if (mImageLoaderIdle && mImageQueue.size() > 0) {ImageRef imageRef = mImageQueue.pop();Message message = mImageLoaderHandler.obtainMessage(MSG_REQUEST,imageRef);mImageLoaderHandler.sendMessage(message);mImageLoaderIdle = false;mRequestQueue.add(imageRef);}}/** * 图片加载线程 */class ImageLoaderHandler extends Handler {public ImageLoaderHandler(Looper looper) {super(looper);}public void handleMessage(Message msg) {if (msg == null)return;switch (msg.what) {case MSG_REQUEST: // 收到请求Bitmap bitmap = null;Bitmap tBitmap = null;if (msg.obj != null && msg.obj instanceof ImageRef) {ImageRef imageRef = (ImageRef) msg.obj;String url = imageRef.url;if (url == null)return;// 如果本地url即读取sd相册图片,则直接读取,不用经过DiskCache// ??? DCIM:DCIM是Android手机摄像头使用的目录,里面存储了用户拍摄的照片和视频,// 以及照片和视频的缩略图(用于缓存提高浏览速度的,删了还会自动生成).if (url.toLowerCase(Locale.getDefault()).contains("dcim")) {// 对图片进行缩放tBitmap = null;BitmapFactory.Options opt = new BitmapFactory.Options();opt.inSampleSize = 1;// 不在内存中生成真实的Bitmap对象opt.inJustDecodeBounds = true;BitmapFactory.decodeFile(url, opt);// pixels*3 if it's RGB and pixels*4// if it's ARGBint bitmapSize = opt.outHeight * opt.outWidth * 4;opt.inSampleSize = bitmapSize / (1000 * 2000);opt.inJustDecodeBounds = false;tBitmap = BitmapFactory.decodeFile(url, opt);if (imageRef.width != 0 && imageRef.height != 0) {// ??? Thumbnail:缩略图bitmap = ThumbnailUtils.extractThumbnail(tBitmap,imageRef.width, imageRef.height,ThumbnailUtils.OPTIONS_RECYCLE_INPUT);isFromNet = true;} else {bitmap = tBitmap;tBitmap = null;}} else {bitmap = mDiskCache.get(url);}if (bitmap != null) {Log.v(TAG, "从disk缓存读取");// 写入map缓存if (imageRef.width != 0 && imageRef.height != 0) {if (mMemoryCache.get(url + imageRef.width+ imageRef.height) == null)mMemoryCache.put(url + imageRef.width+ imageRef.height, bitmap);} else {if (mMemoryCache.get(url) == null)mMemoryCache.put(url, bitmap);}} else { // 处理从网上下载图片try {byte[] data = loadByteArrayFromNetwork(url);if (data != null) {BitmapFactory.Options opt = new BitmapFactory.Options();opt.inSampleSize = 1;opt.inJustDecodeBounds = true;BitmapFactory.decodeByteArray(data, 0,data.length, opt);int bitmapSize = opt.outHeight * opt.outWidth* 4;if (bitmapSize > 1000 * 1200)opt.inSampleSize = 2;opt.inJustDecodeBounds = false;tBitmap = BitmapFactory.decodeByteArray(data,0, data.length, opt);if (imageRef.width != 0 && imageRef.height != 0) {bitmap = ThumbnailUtils.extractThumbnail(tBitmap,imageRef.width,imageRef.height,ThumbnailUtils.OPTIONS_RECYCLE_INPUT);} else {bitmap = tBitmap;tBitmap = null;}if (bitmap != null && url != null) {// 写入SD卡if (imageRef.width != 0&& imageRef.height != 0) {mDiskCache.put(url + imageRef.width+ imageRef.height, bitmap);mMemoryCache.put(url + imageRef.width+ imageRef.height, bitmap);} else {mDiskCache.put(url, bitmap);mMemoryCache.put(url, bitmap);}isFromNet = true;}}} catch (OutOfMemoryError e) {}}}if (mImageManagerHandler != null) {Message message = mImageManagerHandler.obtainMessage(MSG_REPLY, bitmap);mImageManagerHandler.sendMessage(message);}break;case MSG_STOP: // 收到终止指令Looper.myLooper().quit();break;}}}/** UI线程消息处理器 */@SuppressLint("HandlerLeak")private Handler mImageManagerHandler = new Handler() {@Overridepublic void handleMessage(Message msg) {if (msg != null) {switch (msg.what) {case MSG_REPLY: // 收到应答do {ImageRef imageRef = mRequestQueue.remove();if (imageRef == null)break;if (imageRef.imageView == null|| imageRef.imageView.getTag() == null|| imageRef.url == null)break;if (!(msg.obj instanceof Bitmap) || msg.obj == null) {break;}Bitmap bitmap = (Bitmap) msg.obj;// 非同一ImageViewif (!(imageRef.url).equals((String) imageRef.imageView.getTag())) {break;}setImageBitmap(imageRef.imageView, bitmap, isFromNet);isFromNet = false;} while (false);break;}}// 设置闲置标志mImageLoaderIdle = true;// 若服务未关闭,则发送下一个请求。if (mImageLoaderHandler != null) {sendRequest();}}};/** * 添加图片显示渐现动画 *  */private void setImageBitmap(ImageView imageView, Bitmap bitmap,boolean isTran) {if (isTran) {@SuppressWarnings("deprecation")final TransitionDrawable td = new TransitionDrawable(new Drawable[] {new ColorDrawable(android.R.color.transparent),new BitmapDrawable(bitmap) });td.setCrossFadeEnabled(true);imageView.setImageDrawable(td);// 开启限时动画td.startTransition(300);} else {imageView.setImageBitmap(bitmap);}}/** * 从网络获取图片字节数组 *  * @param url * @return */private byte[] loadByteArrayFromNetwork(String url) {try {HttpGet method = new HttpGet(url);HttpResponse response = MyBaseApplication.getInstance().getHttpClient().execute(method);HttpEntity entity = response.getEntity();return EntityUtils.toByteArray(entity);} catch (Exception e) {return null;}}/** * 根据url生成缓存文件完整路径名 *  * @param url * @return */public String urlToFilePath(String url) {// 扩展名位置int index = url.lastIndexOf('.');if (index == -1) {return null;}StringBuilder filePath = new StringBuilder();// 图片存取路径filePath.append(MyBaseApplication.getInstance().getCacheDir().toString()).append('/');// 图片文件名filePath.append(MD5Utils.Md5(url)).append(url.substring(index));return filePath.toString();}/** * Activity#onStop后,ListView不会有残余请求。 */public void stop() {// 清空请求队列mImageQueue.clear();}}

接下来我我们来看看怎么用这个图片缓存的工具类

首先我们需要实力

imageCache = ImageCache.getInstance(this);

用实力去掉用这个方法我们只有传入图片控件和路径后面参数就是默认图片什么的

cache.displayImage(myAccountImg, ServerUrl.baseUrl + a.getImgpath(),
0);



0 0