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;
????/**
?????*?隊(duì)列的調(diào)度方式
?????*/
????privateType?mType?=?Type.LIFO;
????/**
?????*?任務(wù)隊(duì)列
?????*/
????privateLinkedList
????/**
?????*?輪詢的線程
?????*/
????privateThread?mPoolThread;
????privateHandler?mPoolThreadHander;
?
????/**
?????*?運(yùn)行在UI線程的handler,用于給ImageView設(shè)置圖片
?????*/
????privateHandler?mHandler;
?
????/**
?????*?引入一個(gè)值為1的信號(hào)量,防止mPoolThreadHander未初始化完成
?????*/
????privatevolatile?Semaphore?mSemaphore?=?newSemaphore(0);
?
????/**
?????*?引入一個(gè)值為1的信號(hào)量,由于線程池內(nèi)部也有一個(gè)阻塞線程,防止加入任務(wù)的速度過(guò)快,使LIFO效果不明顯
?????*/
????privatevolatile?Semaphore?mPoolSemaphore;
?
????privatestatic?ImageLoader?mInstance;
?
????/**
?????*?隊(duì)列的調(diào)度方式
?????*
?????*?@author?zhy
?????*
?????*/
????publicenum?Type?{
????????FIFO,?LIFO
????}
?
????/**
?????*?單例獲得該實(shí)例對(duì)象
?????*
?????*?@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)?{
????????????????????????}
????????????????????}
????????????????};
????????????????//?釋放一個(gè)信號(hào)量
????????????????mSemaphore.release();
????????????????Looper.loop();
????????????}
????????};
????????mPoolThread.start();
?
????????//?獲取應(yīng)用程序最大可用內(nèi)存
????????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();
????????????????}
????????????});
????????}
?
????}
?
????/**
?????*?添加一個(gè)任務(wù)
?????*
?????*?@param?runnable
?????*/
????privatesynchronized?void?addTask(Runnable?runnable)?{
????????try{
????????????//?請(qǐng)求信號(hào)量,防止mPoolThreadHander為null
????????????if(mPoolThreadHander?==?null)
????????????????mSemaphore.acquire();
????????}catch(InterruptedException?e)?{
????????}
????????mTasks.add(runnable);
?
????????mPoolThreadHander.sendEmptyMessage(0x110);
????}
?
????/**
?????*?取出一個(gè)任務(wù)
?????*
?????*?@return
?????*/
????privatesynchronized?Runnable?getTask()?{
????????if(mType?==?Type.FIFO)?{
????????????returnmTasks.removeFirst();
????????}elseif?(mType?==?Type.LIFO)?{
????????????returnmTasks.removeLast();
????????}
????????returnnull;
????}
?
????/**
?????*?單例獲得該實(shí)例對(duì)象
?????*
?????*?@return
?????*/
????publicstatic?ImageLoader?getInstance(intthreadCount,?Type?type)?{
?
????????if(mInstance?==?null)?{
????????????synchronized(ImageLoader.class)?{
????????????????if(mInstance?==?null)?{
????????????????????mInstance?=?newImageLoader(threadCount,?type);
????????????????}
????????????}
????????}
????????returnmInstance;
????}
?
????/**
?????*?根據(jù)ImageView獲得適當(dāng)?shù)膲嚎s的寬和高
?????*
?????*?@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);
????????}
????}
?
????/**
?????*?計(jì)算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)?{
????????????//?計(jì)算出實(shí)際寬度和目標(biāo)寬度的比率
????????????intwidthRatio?=?Math.round((float)?width?/?(float)?reqWidth);
????????????intheightRatio?=?Math.round((float)?width?/?(float)?reqWidth);
????????????inSampleSize?=?Math.max(widthRatio,?heightRatio);
????????}
????????returninSampleSize;
????}
?
????/**
?????*?根據(jù)計(jì)算的inSampleSize,得到壓縮后圖片
?????*
?????*?@param?pathName
?????*?@param?reqWidth
?????*?@param?reqHeight
?????*?@return
?????*/
????privateBitmap?decodeSampledBitmapFromResource(String?pathName,
????????????intreqWidth,?intreqHeight)?{
????????//?第一次解析將inJustDecodeBounds設(shè)置為true,來(lái)獲取圖片大小
????????finalBitmapFactory.Options?options?=?newBitmapFactory.Options();
????????options.inJustDecodeBounds?=?true;
????????BitmapFactory.decodeFile(pathName,?options);
????????//?調(diào)用上面定義的方法計(jì)算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設(shè)置的最大寬度和高度
?????*
?????*?@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;
????}
?
}
使用很簡(jiǎn)單,如果你在是Adapter中,
雙擊代碼復(fù)制
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);