/** * Copyright (c) 2012-2013, Michael Yang 杨福海 (www.yangfuhai.com). * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package net.tsz.afinal; import android.content.Context; import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Bitmap.CompressFormat; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.text.TextUtils; import android.util.DisplayMetrics; import android.widget.ImageView; import java.lang.ref.WeakReference; import java.util.HashMap; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.ThreadFactory; import net.tsz.afinal.bitmap.core.BitmapCommonUtils; import net.tsz.afinal.bitmap.core.BitmapDisplayConfig; import net.tsz.afinal.bitmap.core.BitmapProcess; import net.tsz.afinal.bitmap.core.BitmapCache; import net.tsz.afinal.bitmap.display.Displayer; import net.tsz.afinal.bitmap.display.SimpleDisplayer; import net.tsz.afinal.bitmap.download.Downloader; import net.tsz.afinal.bitmap.download.SimpleHttpDownloader; import net.tsz.afinal.core.AsyncTask; public class FinalBitmap { private FinalBitmapConfig mConfig; private static BitmapCache mImageCache; private boolean mExitTasksEarly = false; private boolean mPauseWork = false; private final Object mPauseWorkLock = new Object(); private Context mContext; private static ExecutorService bitmapLoadAndDisplayExecutor; private static FinalBitmap mFinalBitmap; ////////////////////////// config method start//////////////////////////////////// private FinalBitmap(Context context) { mContext = context; mConfig = new FinalBitmapConfig(context); configDiskCachePath(BitmapCommonUtils.getDiskCacheDir(context, "afinalCache").getAbsolutePath());//配置缓存路径 configDisplayer(new SimpleDisplayer());//配置显示器 configDownlader(new SimpleHttpDownloader());//配置下载器 } /** * 创建finalbitmap * @param ctx * @return */ public static FinalBitmap create(Context ctx){ if(mFinalBitmap == null){ mFinalBitmap = new FinalBitmap(ctx.getApplicationContext()); mFinalBitmap.init(); } return mFinalBitmap; } /** * 创建finalBitmap * @param ctx * @param diskCachePath 磁盘缓存路径 * @return */ public static FinalBitmap create(Context ctx,String diskCachePath){ if(mFinalBitmap == null){ mFinalBitmap = new FinalBitmap(ctx.getApplicationContext()); mFinalBitmap.configDiskCachePath(diskCachePath); mFinalBitmap.init(); } return mFinalBitmap; } /** * 创建finalBitmap * @param ctx * @param diskCachePath 磁盘缓存路径 * @param memoryCacheSizePercent 缓存大小在当前进程的百分比(0.05-0.8之间) * @return */ public static FinalBitmap create(Context ctx,String diskCachePath,float memoryCacheSizePercent){ if(mFinalBitmap == null){ mFinalBitmap = new FinalBitmap(ctx.getApplicationContext()); mFinalBitmap.configDiskCachePath(diskCachePath); mFinalBitmap.configMemoryCachePercent(memoryCacheSizePercent); mFinalBitmap.init(); } return mFinalBitmap; } /** * 创建finalBitmap * @param ctx * @param diskCachePath 磁盘缓存路径 * @param memoryCacheSize 内存缓存大小 * @return */ public static FinalBitmap create(Context ctx,String diskCachePath,int memoryCacheSize){ if(mFinalBitmap == null){ mFinalBitmap = new FinalBitmap(ctx.getApplicationContext()); mFinalBitmap.configDiskCachePath(diskCachePath); mFinalBitmap.configMemoryCacheSize(memoryCacheSize); mFinalBitmap.init(); } return mFinalBitmap; } /** * 创建finalBitmap * @param ctx * @param diskCachePath 磁盘缓存路径 * @param memoryCacheSizePercent 缓存大小在当前进程的百分比(0.05-0.8之间) * @param threadSize 线程并发数量 * @return */ public static FinalBitmap create(Context ctx,String diskCachePath,float memoryCacheSizePercent,int threadSize){ if(mFinalBitmap == null){ mFinalBitmap = new FinalBitmap(ctx.getApplicationContext()); mFinalBitmap.configDiskCachePath(diskCachePath); mFinalBitmap.configBitmapLoadThreadSize(threadSize); mFinalBitmap.configMemoryCachePercent(memoryCacheSizePercent); mFinalBitmap.init(); } return mFinalBitmap; } /** * 创建finalBitmap * @param ctx * @param diskCachePath 磁盘缓存路径 * @param memoryCacheSize 内存缓存大小 * @param threadSize 线程并发数量 * @return */ public static FinalBitmap create(Context ctx,String diskCachePath,int memoryCacheSize,int threadSize){ if(mFinalBitmap == null){ mFinalBitmap = new FinalBitmap(ctx.getApplicationContext()); mFinalBitmap.configDiskCachePath(diskCachePath); mFinalBitmap.configBitmapLoadThreadSize(threadSize); mFinalBitmap.configMemoryCacheSize(memoryCacheSize); mFinalBitmap.init(); } return mFinalBitmap; } /** * 创建finalBitmap * @param ctx * @param diskCachePath 磁盘缓存路径 * @param memoryCacheSizePercent 缓存大小在当前进程的百分比(0.05-0.8之间) * @param diskCacheSize 磁盘缓存大小 * @param threadSize 线程并发数量 * @return */ public static FinalBitmap create(Context ctx,String diskCachePath,float memoryCacheSizePercent,int diskCacheSize,int threadSize){ if(mFinalBitmap == null){ mFinalBitmap = new FinalBitmap(ctx.getApplicationContext()); mFinalBitmap.configDiskCachePath(diskCachePath); mFinalBitmap.configBitmapLoadThreadSize(threadSize); mFinalBitmap.configMemoryCachePercent(memoryCacheSizePercent); mFinalBitmap.configDiskCacheSize(diskCacheSize); mFinalBitmap.init(); } return mFinalBitmap; } /** * 创建finalBitmap * @param ctx * @param diskCachePath 磁盘缓存路径 * @param memoryCacheSize 内存缓存大小 * @param diskCacheSize 磁盘缓存大小 * @param threadSize 线程并发数量 * @return */ public static FinalBitmap create(Context ctx,String diskCachePath,int memoryCacheSize,int diskCacheSize,int threadSize){ if(mFinalBitmap == null){ mFinalBitmap = new FinalBitmap(ctx.getApplicationContext()); mFinalBitmap.configDiskCachePath(diskCachePath); mFinalBitmap.configBitmapLoadThreadSize(threadSize); mFinalBitmap.configMemoryCacheSize(memoryCacheSize); mFinalBitmap.configDiskCacheSize(diskCacheSize); mFinalBitmap.init(); } return mFinalBitmap; } /** * 设置图片正在加载的时候显示的图片 * @param bitmap */ public FinalBitmap configLoadingImage(Bitmap bitmap) { mConfig.defaultDisplayConfig.setLoadingBitmap(bitmap); return this; } /** * 设置图片正在加载的时候显示的图片 * @param bitmap */ public FinalBitmap configLoadingImage(int resId) { mConfig.defaultDisplayConfig.setLoadingBitmap(BitmapFactory.decodeResource(mContext.getResources(), resId)); return this; } /** * 设置图片加载失败时候显示的图片 * @param bitmap */ public FinalBitmap configLoadfailImage(Bitmap bitmap) { mConfig.defaultDisplayConfig.setLoadfailBitmap(bitmap); return this; } /** * 设置图片加载失败时候显示的图片 * @param resId */ public FinalBitmap configLoadfailImage(int resId) { mConfig.defaultDisplayConfig.setLoadfailBitmap(BitmapFactory.decodeResource(mContext.getResources(), resId)); return this; } /** * 配置默认图片的小的高度 * @param bitmapHeight */ public FinalBitmap configBitmapMaxHeight(int bitmapHeight){ mConfig.defaultDisplayConfig.setBitmapHeight(bitmapHeight); return this; } /** * 配置默认图片的小的宽度 * @param bitmapHeight */ public FinalBitmap configBitmapMaxWidth(int bitmapWidth){ mConfig.defaultDisplayConfig.setBitmapWidth(bitmapWidth); return this; } /** * 设置下载器,比如通过ftp或者其他协议去网络读取图片的时候可以设置这项 * @param downlader * @return */ public FinalBitmap configDownlader(Downloader downlader){ mConfig.downloader = downlader; return this; } /** * 设置显示器,比如在显示的过程中显示动画等 * @param displayer * @return */ public FinalBitmap configDisplayer(Displayer displayer){ mConfig.displayer = displayer; return this; } /** * 设置 图片压缩格式 * 如果是透明的png图片,请用 CompressFormat.PNG * @param format */ public void configCompressFormat(CompressFormat format){ mImageCache.setCompressFormat(format); } /** * 配置 加载图片的时候是否计算图片大小,如果配置为真,则decode图片的时候可能会造成out of memory的异常 * @param neverCalculate 是否decode的时候不计算图片大小 */ public FinalBitmap configCalculateBitmapSizeWhenDecode(boolean neverCalculate){ if (mConfig != null && mConfig.bitmapProcess != null) mConfig.bitmapProcess.configCalculateBitmap(neverCalculate); return this; } /** * 配置磁盘缓存路径 * @param strPath * @return */ private FinalBitmap configDiskCachePath(String strPath){ if(!TextUtils.isEmpty(strPath)){ mConfig.cachePath = strPath; } return this; } /** * 配置内存缓存大小 大于2MB以上有效 * @param size 缓存大小 */ private FinalBitmap configMemoryCacheSize(int size){ mConfig.memCacheSize = size; return this; } /** * 设置应缓存的在APK总内存的百分比,优先级大于configMemoryCacheSize * @param percent 百分比,值的范围是在 0.05 到 0.8之间 */ private FinalBitmap configMemoryCachePercent(float percent){ mConfig.memCacheSizePercent = percent; return this; } /** * 设置磁盘缓存大小 5MB 以上有效 * @param size */ private FinalBitmap configDiskCacheSize(int size){ mConfig.diskCacheSize = size; return this; } /** * 设置加载图片的线程并发数量 * @param size */ private FinalBitmap configBitmapLoadThreadSize(int size){ if(size >= 1) mConfig.poolSize = size; return this; } /** * 这个方法必须被调用后 FinalBitmap 配置才能有效 * @return */ private FinalBitmap init(){ mConfig.init(); BitmapCache.ImageCacheParams imageCacheParams = new BitmapCache.ImageCacheParams(mConfig.cachePath); if(mConfig.memCacheSizePercent>0.05 && mConfig.memCacheSizePercent<0.8){ imageCacheParams.setMemCacheSizePercent(mContext, mConfig.memCacheSizePercent); }else{ if(mConfig.memCacheSize > 1024 * 1024 * 2){ imageCacheParams.setMemCacheSize(mConfig.memCacheSize); }else{ //设置默认的内存缓存大小 imageCacheParams.setMemCacheSizePercent(mContext, 0.3f); } } if(mConfig.diskCacheSize > 1024 * 1024 * 5) imageCacheParams.setDiskCacheSize(mConfig.diskCacheSize); mImageCache = new BitmapCache(imageCacheParams); bitmapLoadAndDisplayExecutor = Executors.newFixedThreadPool(mConfig.poolSize,new ThreadFactory() { public Thread newThread(Runnable r) { Thread t = new Thread(r); // 设置线程的优先级别,让线程先后顺序执行(级别越高,抢到cpu执行的时间越多) t.setPriority(Thread.NORM_PRIORITY - 1); return t; } }); new CacheExecutecTask().execute(CacheExecutecTask.MESSAGE_INIT_DISK_CACHE); return this; } ////////////////////////// config method end//////////////////////////////////// public void display( ImageView imageView,String uri){ doDisplay(imageView,uri,null); } public void display(ImageView imageView,String uri,int imageWidth,int imageHeight){ BitmapDisplayConfig displayConfig = configMap.get(imageWidth+"_"+imageHeight); if(displayConfig==null){ displayConfig = getDisplayConfig(); displayConfig.setBitmapHeight(imageHeight); displayConfig.setBitmapWidth(imageWidth); configMap.put(imageWidth+"_"+imageHeight, displayConfig); } doDisplay(imageView,uri,displayConfig); } public void display(ImageView imageView,String uri,Bitmap loadingBitmap){ BitmapDisplayConfig displayConfig = configMap.get(String.valueOf(loadingBitmap)); if(displayConfig==null){ displayConfig = getDisplayConfig(); displayConfig.setLoadingBitmap(loadingBitmap); configMap.put(String.valueOf(loadingBitmap), displayConfig); } doDisplay(imageView,uri,displayConfig); } public void display(ImageView imageView,String uri,Bitmap loadingBitmap,Bitmap laodfailBitmap){ BitmapDisplayConfig displayConfig = configMap.get(String.valueOf(loadingBitmap)+"_"+String.valueOf(laodfailBitmap)); if(displayConfig==null){ displayConfig = getDisplayConfig(); displayConfig.setLoadingBitmap(loadingBitmap); displayConfig.setLoadfailBitmap(laodfailBitmap); configMap.put(String.valueOf(loadingBitmap)+"_"+String.valueOf(laodfailBitmap), displayConfig); } doDisplay(imageView,uri,displayConfig); } public void display(ImageView imageView,String uri,int imageWidth,int imageHeight,Bitmap loadingBitmap,Bitmap laodfailBitmap){ BitmapDisplayConfig displayConfig = configMap.get(imageWidth+"_"+imageHeight+"_"+String.valueOf(loadingBitmap)+"_"+String.valueOf(laodfailBitmap)); if(displayConfig==null){ displayConfig = getDisplayConfig(); displayConfig.setBitmapHeight(imageHeight); displayConfig.setBitmapWidth(imageWidth); displayConfig.setLoadingBitmap(loadingBitmap); displayConfig.setLoadfailBitmap(laodfailBitmap); configMap.put(imageWidth+"_"+imageHeight+"_"+String.valueOf(loadingBitmap)+"_"+String.valueOf(laodfailBitmap), displayConfig); } doDisplay(imageView,uri,displayConfig); } public void display( ImageView imageView,String uri,BitmapDisplayConfig config){ doDisplay(imageView,uri,config); } private void doDisplay(ImageView imageView, String uri, BitmapDisplayConfig displayConfig) { if (TextUtils.isEmpty(uri) || imageView == null) { return; } if(displayConfig == null) displayConfig = mConfig.defaultDisplayConfig; Bitmap bitmap = null; if (mImageCache != null) { bitmap = mImageCache.getBitmapFromMemCache(uri); } if (bitmap != null) { imageView.setImageBitmap(bitmap); }else if (checkImageTask(uri, imageView)) { final BitmapLoadAndDisplayTask task = new BitmapLoadAndDisplayTask(imageView, displayConfig); //设置默认图片 final AsyncDrawable asyncDrawable = new AsyncDrawable(mContext.getResources(), displayConfig.getLoadingBitmap(), task); imageView.setImageDrawable(asyncDrawable); task.executeOnExecutor(bitmapLoadAndDisplayExecutor, uri); } } private HashMap<String, BitmapDisplayConfig> configMap= new HashMap<String, BitmapDisplayConfig>(); private BitmapDisplayConfig getDisplayConfig(){ BitmapDisplayConfig config = new BitmapDisplayConfig(); config.setAnimation(mConfig.defaultDisplayConfig.getAnimation()); config.setAnimationType(mConfig.defaultDisplayConfig.getAnimationType()); config.setBitmapHeight(mConfig.defaultDisplayConfig.getBitmapHeight()); config.setBitmapWidth(mConfig.defaultDisplayConfig.getBitmapWidth()); config.setLoadfailBitmap(mConfig.defaultDisplayConfig.getLoadfailBitmap()); config.setLoadingBitmap(mConfig.defaultDisplayConfig.getLoadingBitmap()); return config; } private void initDiskCacheInternalInBackgroud() { if (mImageCache != null) { mImageCache.initDiskCache(); } if (mConfig != null && mConfig.bitmapProcess != null) { mConfig.bitmapProcess.initHttpDiskCache(); } } private void clearCacheInternalInBackgroud() { if (mImageCache != null) { mImageCache.clearCache(); } if (mConfig != null && mConfig.bitmapProcess != null) { mConfig.bitmapProcess.clearCacheInternal(); } } private void clearMemoryCacheInBackgroud(){ if (mImageCache != null) { mImageCache.clearMemoryCache(); } } private void clearDiskCacheInBackgroud(){ if (mImageCache != null) { mImageCache.clearDiskCache(); } if (mConfig != null && mConfig.bitmapProcess != null) { mConfig.bitmapProcess.clearCacheInternal(); } } private void clearCacheInBackgroud(String key){ if (mImageCache != null) { mImageCache.clearCache(key); } } private void clearDiskCacheInBackgroud(String key){ if (mImageCache != null) { mImageCache.clearDiskCache(key); } } private void clearMemoryCacheInBackgroud(String key){ if (mImageCache != null) { mImageCache.clearMemoryCache(key); } } private void flushCacheInternalInBackgroud() { if (mImageCache != null) { mImageCache.flush(); } if (mConfig != null && mConfig.bitmapProcess != null) { mConfig.bitmapProcess.flushCacheInternal(); } } private void closeCacheInternalInBackgroud() { if (mImageCache != null) { mImageCache.close(); mImageCache = null; } if (mConfig != null && mConfig.bitmapProcess != null) { mConfig.bitmapProcess.clearCacheInternal(); } } /** * 网络加载bitmap * @param data * @return */ private Bitmap processBitmap(String uri,BitmapDisplayConfig config) { if (mConfig != null && mConfig.bitmapProcess != null) { return mConfig.bitmapProcess.processBitmap(uri,config); } return null; } public void setExitTasksEarly(boolean exitTasksEarly) { mExitTasksEarly = exitTasksEarly; } /** * activity onResume的时候调用这个方法,让加载图片线程继续 */ public void onResume(){ setExitTasksEarly(false); } /** * activity onPause的时候调用这个方法,让线程暂停 */ public void onPause() { setExitTasksEarly(true); flushCache(); } /** * activity onDestroy的时候调用这个方法,释放缓存 */ public void onDestroy() { closeCache(); } /** * 清除所有缓存(磁盘和内存) */ public void clearCache() { new CacheExecutecTask().execute(CacheExecutecTask.MESSAGE_CLEAR); } /** * 根据key清除指定的内存缓存 * @param key */ public void clearCache(String key) { new CacheExecutecTask().execute(CacheExecutecTask.MESSAGE_CLEAR_KEY,key); } /** * 清除缓存 */ public void clearMemoryCache() { new CacheExecutecTask().execute(CacheExecutecTask.MESSAGE_CLEAR_MEMORY); } /** * 根据key清除指定的内存缓存 * @param key */ public void clearMemoryCache(String key) { new CacheExecutecTask().execute(CacheExecutecTask.MESSAGE_CLEAR_KEY_IN_MEMORY,key); } /** * 清除磁盘缓存 */ public void clearDiskCache() { new CacheExecutecTask().execute(CacheExecutecTask.MESSAGE_CLEAR_DISK); } /** * 根据key清除指定的内存缓存 * @param key */ public void clearDiskCache(String key) { new CacheExecutecTask().execute(CacheExecutecTask.MESSAGE_CLEAR_KEY_IN_DISK,key); } /** * 刷新缓存 */ public void flushCache() { new CacheExecutecTask().execute(CacheExecutecTask.MESSAGE_FLUSH); } /** * 关闭缓存 */ public void closeCache() { new CacheExecutecTask().execute(CacheExecutecTask.MESSAGE_CLOSE); } /** * 退出正在加载的线程,程序退出的时候调用词方法 * @param exitTasksEarly */ public void exitTasksEarly(boolean exitTasksEarly) { mExitTasksEarly = exitTasksEarly; if(exitTasksEarly) pauseWork(false);//让暂停的线程结束 } /** * 暂停正在加载的线程,监听listview或者gridview正在滑动的时候条用词方法 * @param pauseWork true停止暂停线程,false继续线程 */ public void pauseWork(boolean pauseWork) { synchronized (mPauseWorkLock) { mPauseWork = pauseWork; if (!mPauseWork) { mPauseWorkLock.notifyAll(); } } } private static BitmapLoadAndDisplayTask getBitmapTaskFromImageView(ImageView imageView) { if (imageView != null) { final Drawable drawable = imageView.getDrawable(); if (drawable instanceof AsyncDrawable) { final AsyncDrawable asyncDrawable = (AsyncDrawable) drawable; return asyncDrawable.getBitmapWorkerTask(); } } return null; } /** * 检测 imageView中是否已经有线程在运行 * @param data * @param imageView * @return true 没有 false 有线程在运行了 */ public static boolean checkImageTask(Object data, ImageView imageView) { final BitmapLoadAndDisplayTask bitmapWorkerTask = getBitmapTaskFromImageView(imageView); if (bitmapWorkerTask != null) { final Object bitmapData = bitmapWorkerTask.data; if (bitmapData == null || !bitmapData.equals(data)) { bitmapWorkerTask.cancel(true); } else { // 同一个线程已经在执行 return false; } } return true; } private static class AsyncDrawable extends BitmapDrawable { private final WeakReference<BitmapLoadAndDisplayTask> bitmapWorkerTaskReference; public AsyncDrawable(Resources res, Bitmap bitmap,BitmapLoadAndDisplayTask bitmapWorkerTask) { super(res, bitmap); bitmapWorkerTaskReference = new WeakReference<BitmapLoadAndDisplayTask>( bitmapWorkerTask); } public BitmapLoadAndDisplayTask getBitmapWorkerTask() { return bitmapWorkerTaskReference.get(); } } /** * @title 缓存操作的异步任务 * @description 操作缓存 * @company 探索者网络工作室(www.tsz.net) * @author michael Young (www.YangFuhai.com) * @version 1.0 * @created 2012-10-28 */ private class CacheExecutecTask extends AsyncTask<Object, Void, Void> { public static final int MESSAGE_CLEAR = 0; public static final int MESSAGE_INIT_DISK_CACHE = 1; public static final int MESSAGE_FLUSH = 2; public static final int MESSAGE_CLOSE = 3; public static final int MESSAGE_CLEAR_MEMORY = 4; public static final int MESSAGE_CLEAR_DISK = 5; public static final int MESSAGE_CLEAR_KEY = 6; public static final int MESSAGE_CLEAR_KEY_IN_MEMORY = 7; public static final int MESSAGE_CLEAR_KEY_IN_DISK = 8; @Override protected Void doInBackground(Object... params) { switch ((Integer) params[0]) { case MESSAGE_CLEAR: clearCacheInternalInBackgroud(); break; case MESSAGE_INIT_DISK_CACHE: initDiskCacheInternalInBackgroud(); break; case MESSAGE_FLUSH: clearMemoryCacheInBackgroud(); flushCacheInternalInBackgroud(); break; case MESSAGE_CLOSE: clearMemoryCacheInBackgroud(); closeCacheInternalInBackgroud(); case MESSAGE_CLEAR_MEMORY: clearMemoryCacheInBackgroud(); break; case MESSAGE_CLEAR_DISK: clearDiskCacheInBackgroud(); break; case MESSAGE_CLEAR_KEY: clearCacheInBackgroud(String.valueOf(params[1])); break; case MESSAGE_CLEAR_KEY_IN_MEMORY: clearMemoryCacheInBackgroud(String.valueOf(params[1])); break; case MESSAGE_CLEAR_KEY_IN_DISK: clearDiskCacheInBackgroud(String.valueOf(params[1])); break; } return null; } } /** * bitmap下载显示的线程 * @author michael yang */ private class BitmapLoadAndDisplayTask extends AsyncTask<Object, Void, Bitmap> { private Object data; private final WeakReference<ImageView> imageViewReference; private final BitmapDisplayConfig displayConfig; public BitmapLoadAndDisplayTask(ImageView imageView,BitmapDisplayConfig config) { imageViewReference = new WeakReference<ImageView>(imageView); displayConfig = config; } @Override protected Bitmap doInBackground(Object... params) { data = params[0]; final String dataString = String.valueOf(data); Bitmap bitmap = null; synchronized (mPauseWorkLock) { while (mPauseWork && !isCancelled()) { try { mPauseWorkLock.wait(); } catch (InterruptedException e) { } } } if (mImageCache != null && !isCancelled() && getAttachedImageView() != null && !mExitTasksEarly) { bitmap = mImageCache.getBitmapFromDiskCache(dataString); } if (bitmap == null && !isCancelled()&& getAttachedImageView() != null && !mExitTasksEarly) { bitmap = processBitmap(dataString,displayConfig); } if (bitmap != null && mImageCache != null) { mImageCache.addBitmapToCache(dataString, bitmap); } return bitmap; } @Override protected void onPostExecute(Bitmap bitmap) { if (isCancelled() || mExitTasksEarly) { bitmap = null; } // 判断线程和当前的imageview是否是匹配 final ImageView imageView = getAttachedImageView(); if (bitmap != null && imageView != null) { mConfig.displayer.loadCompletedisplay(imageView,bitmap,displayConfig); }else if(bitmap == null && imageView!=null ){ mConfig.displayer.loadFailDisplay(imageView, displayConfig.getLoadfailBitmap()); } } @Override protected void onCancelled(Bitmap bitmap) { super.onCancelled(bitmap); synchronized (mPauseWorkLock) { mPauseWorkLock.notifyAll(); } } /** * 获取线程匹配的imageView,防止出现闪动的现象 * @return */ private ImageView getAttachedImageView() { final ImageView imageView = imageViewReference.get(); final BitmapLoadAndDisplayTask bitmapWorkerTask = getBitmapTaskFromImageView(imageView); if (this == bitmapWorkerTask) { return imageView; } return null; } } /** * @title 配置信息 * @description FinalBitmap的配置信息 * @company 探索者网络工作室(www.tsz.net) * @author michael Young (www.YangFuhai.com) * @version 1.0 * @created 2012-10-28 */ private class FinalBitmapConfig { public String cachePath; public Displayer displayer; public Downloader downloader; public BitmapProcess bitmapProcess; public BitmapDisplayConfig defaultDisplayConfig; public float memCacheSizePercent;//缓存百分比,android系统分配给每个apk内存的大小 public int memCacheSize;//内存缓存百分比 public int diskCacheSize;//磁盘百分比 public int poolSize = 3;//默认的线程池线程并发数量 public int originalDiskCacheSize = 30 * 1024 * 1024;//50MB public FinalBitmapConfig(Context context) { defaultDisplayConfig = new BitmapDisplayConfig(); defaultDisplayConfig.setAnimation(null); defaultDisplayConfig.setAnimationType(BitmapDisplayConfig.AnimationType.fadeIn); //设置图片的显示最大尺寸(为屏幕的大小,默认为屏幕宽度的1/3) DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics(); int defaultWidth = (int)Math.floor(displayMetrics.widthPixels/4); defaultDisplayConfig.setBitmapHeight(defaultWidth); defaultDisplayConfig.setBitmapWidth(defaultWidth); } public void init() { if(downloader==null) downloader = new SimpleHttpDownloader(); if(displayer==null) displayer = new SimpleDisplayer(); bitmapProcess = new BitmapProcess(downloader,cachePath,originalDiskCacheSize); } } }