android lrucache使用
扫描二维码
随时随地手机看文章
importjava.lang.reflect.Field;
importjava.util.LinkedList;
importjava.util.concurrent.ExecutorService;
importjava.util.concurrent.Executors;
importjava.util.concurrent.Semaphore;
importandroid.graphics.Bitmap;
importandroid.graphics.BitmapFactory;
importandroid.os.Handler;
importandroid.os.Looper;
importandroid.os.Message;
importandroid.support.v4.util.LruCache;
importandroid.util.DisplayMetrics;
importandroid.view.ViewGroup.LayoutParams;
importandroid.widget.ImageView;
publicclass ImageLoader {
/**
* 图片缓存的核心类
*/
privateLruCache
/**
* 线程池
*/
privateExecutorService mThreadPool;
/**
* 队列的调度方式
*/
privateType mType = Type.LIFO;
/**
* 任务队列
*/
privateLinkedList
/**
* 轮询的线程
*/
privateThread mPoolThread;
privateHandler mPoolThreadHander;
/**
* 运行在UI线程的handler,用于给ImageView设置图片
*/
privateHandler mHandler;
/**
* 引入一个值为1的信号量,防止mPoolThreadHander未初始化完成
*/
privatevolatile Semaphore mSemaphore = newSemaphore(0);
/**
* 引入一个值为1的信号量,由于线程池内部也有一个阻塞线程,防止加入任务的速度过快,使LIFO效果不明显
*/
privatevolatile Semaphore mPoolSemaphore;
privatestatic ImageLoader mInstance;
/**
* 队列的调度方式
*
* @author zhy
*
*/
publicenum Type {
FIFO, LIFO
}
/**
* 单例获得该实例对象
*
* @return
*/
publicstatic ImageLoader getInstance() {
if(mInstance == null) {
synchronized(ImageLoader.class) {
if(mInstance == null) {
mInstance = newImageLoader(1, Type.LIFO);
}
}
}
returnmInstance;
}
privateImageLoader(intthreadCount, Type type) {
init(threadCount, type);
}
privatevoid init(intthreadCount, Type type) {
// loop thread
mPoolThread = newThread() {
@Override
publicvoid run() {
Looper.prepare();
mPoolThreadHander = newHandler() {
@Override
publicvoid handleMessage(Message msg) {
mThreadPool.execute(getTask());
try{
mPoolSemaphore.acquire();
}catch(InterruptedException e) {
}
}
};
// 释放一个信号量
mSemaphore.release();
Looper.loop();
}
};
mPoolThread.start();
// 获取应用程序最大可用内存
intmaxMemory = (int) Runtime.getRuntime().maxMemory();
intcacheSize = maxMemory / 8;
mLruCache = newLruCache
@Override
protectedint sizeOf(String key, Bitmap value) {
returnvalue.getRowBytes() * value.getHeight();
};
};
mThreadPool = Executors.newFixedThreadPool(threadCount);
mPoolSemaphore = newSemaphore(threadCount);
mTasks = newLinkedList
mType = type == null? Type.LIFO : type;
}
/**
* 加载图片
*
* @param path
* @param imageView
*/
publicvoid loadImage(finalString path, finalImageView imageView) {
// set tag
imageView.setTag(path);
// UI线程
if(mHandler == null) {
mHandler = newHandler() {
@Override
publicvoid handleMessage(Message msg) {
ImgBeanHolder holder = (ImgBeanHolder) msg.obj;
ImageView imageView = holder.imageView;
Bitmap bm = holder.bitmap;
String path = holder.path;
if(imageView.getTag().toString().equals(path)) {
imageView.setImageBitmap(bm);
}
}
};
}
Bitmap bm = getBitmapFromLruCache(path);
if(bm != null) {
ImgBeanHolder holder = newImgBeanHolder();
holder.bitmap = bm;
holder.imageView = imageView;
holder.path = path;
Message message = Message.obtain();
message.obj = holder;
mHandler.sendMessage(message);
}else{
addTask(newRunnable() {
@Override
publicvoid run() {
ImageSize imageSize = getImageViewWidth(imageView);
intreqWidth = imageSize.width;
intreqHeight = imageSize.height;
Bitmap bm = decodeSampledBitmapFromResource(path, reqWidth,
reqHeight);
addBitmapToLruCache(path, bm);
ImgBeanHolder holder = newImgBeanHolder();
holder.bitmap = getBitmapFromLruCache(path);
holder.imageView = imageView;
holder.path = path;
Message message = Message.obtain();
message.obj = holder;
// Log.e("TAG", "mHandler.sendMessage(message);");
mHandler.sendMessage(message);
mPoolSemaphore.release();
}
});
}
}
/**
* 添加一个任务
*
* @param runnable
*/
privatesynchronized void addTask(Runnable runnable) {
try{
// 请求信号量,防止mPoolThreadHander为null
if(mPoolThreadHander == null)
mSemaphore.acquire();
}catch(InterruptedException e) {
}
mTasks.add(runnable);
mPoolThreadHander.sendEmptyMessage(0x110);
}
/**
* 取出一个任务
*
* @return
*/
privatesynchronized Runnable getTask() {
if(mType == Type.FIFO) {
returnmTasks.removeFirst();
}elseif (mType == Type.LIFO) {
returnmTasks.removeLast();
}
returnnull;
}
/**
* 单例获得该实例对象
*
* @return
*/
publicstatic ImageLoader getInstance(intthreadCount, Type type) {
if(mInstance == null) {
synchronized(ImageLoader.class) {
if(mInstance == null) {
mInstance = newImageLoader(threadCount, type);
}
}
}
returnmInstance;
}
/**
* 根据ImageView获得适当的压缩的宽和高
*
* @param imageView
* @return
*/
privateImageSize getImageViewWidth(ImageView imageView) {
ImageSize imageSize = newImageSize();
finalDisplayMetrics displayMetrics = imageView.getContext()
.getResources().getDisplayMetrics();
finalLayoutParams params = imageView.getLayoutParams();
intwidth = params.width == LayoutParams.WRAP_CONTENT ? 0: imageView
.getWidth();// Get actual image width
if(width <= 0)
width = params.width; // Get layout width parameter
if(width <= 0)
width = getImageViewFieldValue(imageView, "mMaxWidth");// Check
// maxWidth
// parameter
if(width <= 0)
width = displayMetrics.widthPixels;
intheight = params.height == LayoutParams.WRAP_CONTENT ? 0: imageView
.getHeight();// Get actual image height
if(height <= 0)
height = params.height; // Get layout height parameter
if(height <= 0)
height = getImageViewFieldValue(imageView, "mMaxHeight");// Check
// maxHeight
// parameter
if(height <= 0)
height = displayMetrics.heightPixels;
imageSize.width = width;
imageSize.height = height;
returnimageSize;
}
/**
* 从LruCache中获取一张图片,如果不存在就返回null。
*/
privateBitmap getBitmapFromLruCache(String key) {
returnmLruCache.get(key);
}
/**
* 往LruCache中添加一张图片
*
* @param key
* @param bitmap
*/
privatevoid addBitmapToLruCache(String key, Bitmap bitmap) {
if(getBitmapFromLruCache(key) == null) {
if(bitmap != null)
mLruCache.put(key, bitmap);
}
}
/**
* 计算inSampleSize,用于压缩图片
*
* @param options
* @param reqWidth
* @param reqHeight
* @return
*/
privateint calculateInSampleSize(BitmapFactory.Options options,
intreqWidth, intreqHeight) {
// 源图片的宽度
intwidth = options.outWidth;
intheight = options.outHeight;
intinSampleSize = 1;
if(width > reqWidth && height > reqHeight) {
// 计算出实际宽度和目标宽度的比率
intwidthRatio = Math.round((float) width / (float) reqWidth);
intheightRatio = Math.round((float) width / (float) reqWidth);
inSampleSize = Math.max(widthRatio, heightRatio);
}
returninSampleSize;
}
/**
* 根据计算的inSampleSize,得到压缩后图片
*
* @param pathName
* @param reqWidth
* @param reqHeight
* @return
*/
privateBitmap decodeSampledBitmapFromResource(String pathName,
intreqWidth, intreqHeight) {
// 第一次解析将inJustDecodeBounds设置为true,来获取图片大小
finalBitmapFactory.Options options = newBitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(pathName, options);
// 调用上面定义的方法计算inSampleSize值
options.inSampleSize = calculateInSampleSize(options, reqWidth,
reqHeight);
// 使用获取到的inSampleSize值再次解析图片
options.inJustDecodeBounds = false;
Bitmap bitmap = BitmapFactory.decodeFile(pathName, options);
returnbitmap;
}
privateclass ImgBeanHolder {
Bitmap bitmap;
ImageView imageView;
String path;
}
privateclass ImageSize {
intwidth;
intheight;
}
/**
* 反射获得ImageView设置的最大宽度和高度
*
* @param object
* @param fieldName
* @return
*/
privatestatic int getImageViewFieldValue(Object object, String fieldName) {
intvalue = 0;
try{
Field field = ImageView.class.getDeclaredField(fieldName);
field.setAccessible(true);
intfieldValue = (Integer) field.get(object);
if(fieldValue > 0&& fieldValue < Integer.MAX_VALUE) {
value = fieldValue;
}
}catch(Exception e) {
}
returnvalue;
}
}
使用很简单,如果你在是Adapter中,
双击代码复制
ImageItem item = getItem(position);
String path = item.getPath();
ImageView imageView = holder.getImageView(R.id.img_plant);
ImageLoader.getInstance().loadImage(path, imageView);
imageView.setImageResource(R.drawable.pictures_no);