BitMap高效显示策略(三):使用内存缓存技术和BitmapFactory.Options.inBitmap参数

来源:互联网 发布:linux aria2 多线程 编辑:程序博客网 时间:2024/06/05 18:03

接上篇BitMap高效显示策略(二):在ListView上异步加载网络图片,ListView在屏幕上来回划动时,重新进入屏幕范围的Item会重新从网络上加载一次图片,这样做会降低效率,并且浪费流量,更好的方法是使用缓存,缓存可以分为2级:内存缓存和文件缓存,这篇只讨论内存缓存:当ListView需要在指定Item上加载图片时,先根据下载URL检查缓存中是否存在这个BitmapDrawable,如果存在,直接显示在ImageView上,不存在,则从网络上下载。当一个Bitmap下载完毕后,加入内存缓存。

按照以上思路,接上篇代码,改写loadImage方法,伪代码为:

[java] view plaincopy
  1. public void loadImage(String url, ImageView imageView) {  
  2.     if (url == null) {  
  3.         return;  
  4.     }  
  5.       
  6.     BitmapDrawable bitmapDrawable = null;  
  7.       
  8.     //先从内存缓存中读取  
  9.                if (缓存 != null) {  
  10.             bitmapDrawable = 缓存中获取bitmapDrawable方法(url);  
  11.                }  
  12.         
  13.                if (bitmapDrawable != null) {  
  14.             imageView.setImageDrawable(bitmapDrawable);  
  15.                }  
  16.                //否则下载  
  17.                else if (cancelPotentialWork(url, imageView)) {  
  18.   
  19.         final BitmapWorkerTask task = new BitmapWorkerTask(url, imageView);  
  20.         final AsyncDrawable asyncDrawable = new AsyncDrawable(mResources,  
  21.                 task);  
  22.         imageView.setImageDrawable(asyncDrawable);  
  23.   
  24.         task.executeOnExecutor(ImageAsyncTask.DUAL_THREAD_EXECUTOR);  
  25.     }  
  26. }  
同时,在BitmapWorkerTask的doInBackground中,在Bitmap加载完毕后将drawable加入缓存

[java] view plaincopy
  1. if (bitmap == null && !isCancelled()  
  2.         && getAttachedImageView() != null && !mExitTasksEarly) {  
  3.     bitmap = processBitmap(mUrl);  
  4. }  
  5.   
  6. if (bitmap != null) {  
  7.     drawable = new BitmapDrawable(mResources, bitmap);  
  8.     if (缓存 != null) {  
  9.         加入缓存  
  10.     }  
  11. }  

接下来,实现以上伪码

首先创建ImageCache这个类,ImageCache用于封装缓存对象,ImageCache内使用LruCache类作为内存缓存,LruCache内部实现中,使用了LinkedHashMap,具体实现分析可以参照android.util.LruCache主要代码分析 。

ImageCache的实现:

@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2)public class ImageCache {private static final String TAG = "TEST";//缓存基本设置private static final int DEFAULT_MEM_CACHE_SIZE = 1024 * 5; // 内存缓存默认大小5MBprivate static final boolean DEFAULT_MEM_CACHE_ENABLED = true;//内存缓存private LruCache<String, BitmapDrawable> mMemoryCache;private ImageCacheParams mCacheParams;public static class ImageCacheParams {//mempublic int memCacheSize = DEFAULT_MEM_CACHE_SIZE;public boolean memoryCacheEnabled = DEFAULT_MEM_CACHE_ENABLED;/*** * 手动设置内存缓存大小 * @param percent 缓存大小占最大可用内存的比例 */public void setMemCacheSizePercent(float percent) {if (percent < 0.01f || percent > 0.8f) {throw new IllegalArgumentException("setMemCacheSizePercent - percent must be "+ "between 0.01 and 0.8 (inclusive)");}memCacheSize = Math.round(percent * Runtime.getRuntime().maxMemory() / 1024);}}/** *  * 放在no UI的fragment中,保证屏幕旋转时不被回收 * @param fragmentManager * @param cacheParams * @return */public static ImageCache getInstance(FragmentManager fragmentManager, ImageCacheParams cacheParams) {final RetainFragment mRetainFragment = findOrCreateRetainFragment(fragmentManager);ImageCache imageCache = (ImageCache) mRetainFragment.getObject();if (imageCache == null) {            imageCache = new ImageCache(cacheParams);            mRetainFragment.setObject(imageCache);        }        return imageCache;}    private ImageCache(ImageCacheParams cacheParams) {        init(cacheParams);    }        private void init(ImageCacheParams cacheParams) {    mCacheParams = cacheParams;    if (mCacheParams.memoryCacheEnabled) {    mMemoryCache = new LruCache<String, BitmapDrawable>(mCacheParams.memCacheSize) {@Overrideprotected void entryRemoved(boolean evicted, String key,BitmapDrawable oldValue, BitmapDrawable newValue) {if (RecyclingBitmapDrawable.class.isInstance(oldValue)) {//减少缓存计数((RecyclingBitmapDrawable) oldValue).setIsCached(false);}}@Overrideprotected int sizeOf(String key, BitmapDrawable bitmapDrawable) {final int bitmapSize = getBitmapSize(bitmapDrawable) / 1024;return bitmapSize == 0 ? 1 : bitmapSize;}        };    }    }        /**     * 清空缓存     */    public void clearCache() {    if (mMemoryCache != null) {            mMemoryCache.evictAll();        }    }            /**     * 获取bitmap大小     * @param bitmapDrawable     * @return     */    @TargetApi(Build.VERSION_CODES.KITKAT)public static int getBitmapSize(BitmapDrawable bitmapDrawable) {        Bitmap bitmap = bitmapDrawable.getBitmap();    //4.4    if (Build.VERSION.SDK_INT >= VERSION_CODES.KITKAT) {    return bitmap.getAllocationByteCount();    }    //3.1及以上    if (Build.VERSION.SDK_INT >= VERSION_CODES.HONEYCOMB_MR1) {    return  bitmap.getByteCount();    }    //3.1之前的版本    return bitmap.getRowBytes() * bitmap.getHeight();    }        /**获取内存缓存中的图片     * @param url     * @return     */    public BitmapDrawable getBitmapFromMemCache(String url) {    BitmapDrawable bitmapDrawable = null;        if (mMemoryCache != null) {    bitmapDrawable = mMemoryCache.get(url);    }        if (bitmapDrawable != null) {            Log.d("TEST", "Memory cache hit");        }        return bitmapDrawable;    }        /**     * 图片加入内存缓存     * @param data     * @param value     */    public void addBitmapToCache(String url, BitmapDrawable bitmapDrawable) {    if (url == null || bitmapDrawable == null) {    return;    }        if (mMemoryCache != null) {    //如果是RecyclingBitmapDrawable,增加缓存计数    if (RecyclingBitmapDrawable.class.isInstance(bitmapDrawable)) {    ((RecyclingBitmapDrawable) bitmapDrawable).setIsCached(true);    }        mMemoryCache.put(url, bitmapDrawable);    }    }private static RetainFragment findOrCreateRetainFragment(FragmentManager fm) {RetainFragment mRetainFragment = (RetainFragment) fm.findFragmentByTag(ImageCache.class.getName());if (mRetainFragment == null) {mRetainFragment = new RetainFragment();fm.beginTransaction().add(mRetainFragment, ImageCache.class.getName()).commitAllowingStateLoss();;}return mRetainFragment;}/** * 后台Fragment用于在横竖屏切换时保存ImageCache对象。 * */public static class RetainFragment extends Fragment {private Object object;public Object getObject() {return object;}public void setObject(Object object) {this.object = object;}@Override        public void onCreate(Bundle savedInstanceState) {            super.onCreate(savedInstanceState);            setRetainInstance(true);        }}}


LruCache<String, BitmapDrawable> mMemoryCache是ImageCache的核心。图片的Url作为LruCache的键,加载完后的BitmapDrawable作为值,以key/value的形式存储。

ImageCacheParams封装了缓存的一些设定,setMemCacheSizePercent方法设置内存缓存大小占应用程序最大可用内存的比例,如果不设置,默认大小是5MB。

ImageCache实例通过静态方法getInstance获取,ImageCache实例存储在RetainFragment中,RetainFragment是一个没有UI的Fragment,在onCreate方法中, 设置了setRetainInstance(true);所以这个Fragment在屏幕旋转时,不会重新创建,这样得以在配置变化时保存ImageCache对象并且Activity重新创建后快速加载缓存。

构造方法中调用了init方法,init方法中,初始化mMemoryCache对象, 重写了其entryRemoved 和sizeof方法,在entryRemoved中,减少RecyclingBitmapDrawable的缓存计数。sizeOf是用来计算单个缓存的BitmapDrawable对象的大小的,getBitmapSize中根据不同安卓版本,调用不同的计算方法。

[java] view plaincopy
  1. mImageWorker = new ImageFetcher(getActivity(), 50);  
  2.   
  3. ImageCache.ImageCacheParams cacheParams = new ImageCache.ImageCacheParams();  
  4.   
  5. //内存缓存大小为应用可用内存的1/4  
  6. cacheParams.setMemCacheSizePercent(0.25f);  
  7.   
  8. mImageWorker.initImageCache(getActivity().getSupportFragmentManager(), cacheParams);  
这样就可以使用缓存对象了。

修改 loadImage代码:

public void loadImage(String url, ImageView imageView) {if (url == null) {return;}BitmapDrawable bitmapDrawable = null;//先从内存缓存中读取        if (mImageCache != null) {        bitmapDrawable = mImageCache.getBitmapFromMemCache(url);        }                if (bitmapDrawable != null) {        imageView.setImageDrawable(bitmapDrawable);        }        //否则下载        else if (cancelPotentialWork(url, imageView)) {final BitmapWorkerTask task = new BitmapWorkerTask(url, imageView);final AsyncDrawable asyncDrawable = new AsyncDrawable(mResources,task);imageView.setImageDrawable(asyncDrawable);task.executeOnExecutor(ImageAsyncTask.DUAL_THREAD_EXECUTOR);}}


修改BitmapWorkerTask的doInBackground:

[java] view plaincopy
  1.         @Override  
  2.         protected BitmapDrawable doInBackground(Void... params) {  
  3.   
  4.             Bitmap bitmap = null;  
  5.             BitmapDrawable drawable = null;  
  6.   
  7.             synchronized (mPauseWorkLock) {  
  8.                 while (mPauseWork && !isCancelled()) {  
  9.                     try {  
  10.                         mPauseWorkLock.wait();  
  11.                     } catch (InterruptedException e) {  
  12.                         e.printStackTrace();  
  13.                     }  
  14.                 }  
  15.             }  
  16.   
  17.             if (bitmap == null && !isCancelled()  
  18.                     && getAttachedImageView() != null && !mExitTasksEarly) {  
  19.                 bitmap = processBitmap(mUrl);  
  20.             }  
  21.   
  22.             if (bitmap != null) {  
  23.                 if (Build.VERSION.SDK_INT >= VERSION_CODES.HONEYCOMB) {  
  24.                                     drawable = new BitmapDrawable(mResources, bitmap);  
  25.                                 } else {  
  26.                                     // 3.0以下版本,创建自动回收的BitmapDrawable  
  27.                                     drawable = new RecyclingBitmapDrawable(mResources, bitmap);  
  28.                                 }  
  29.                   
  30.                 //加入缓存  
  31.                 if (mImageCache != null) {  
  32.                                     mImageCache.addBitmapToCache(mUrl, drawable);  
  33.                                 }   
  34.                 }  
  35.   
  36.             return drawable;  
  37.         }  
这样内存缓存就添加完成了。


BitmapFactory.Options.inBitmap:

在Android 3.0 引进了BitmapFactory.Options.inBitmap. 如果这个值被设置了,decode方法会在加载内容的时候去重用已经存在的bitmap. 这意味着bitmap的内存是被重新利用的,这样可以提升性能, 并且减少了内存的分配与回收。然而,使用inBitmap有一些限制。特别是在Android 4.4 之前,只支持同等大小的位图。

在ImageCache中加入全局变量:

private Set<SoftReference<Bitmap>> mReusableBitmaps;

这是个存放可重用Bitmap的软引用的集合

修改init方法:

[java] view plaincopy
  1. private void init(ImageCacheParams cacheParams) {  
  2.         mCacheParams = cacheParams;  
  3.         if (mCacheParams.memoryCacheEnabled) {  
  4.             //Android3.0以上可以重用bitmap内存,将内存缓存中的回收项重用。  
  5.             if (Build.VERSION.SDK_INT >= VERSION_CODES.HONEYCOMB) {  
  6.                 mReusableBitmaps =  
  7.                         Collections.synchronizedSet(new HashSet<SoftReference<Bitmap>>());  
  8.             }  
  9.               
  10.             mMemoryCache = new LruCache<String, BitmapDrawable>(mCacheParams.memCacheSize) {  
  11.   
  12.                 @Override  
  13.                 protected void entryRemoved(boolean evicted, String key,  
  14.                         BitmapDrawable oldValue, BitmapDrawable newValue) {  
  15.                     if (RecyclingBitmapDrawable.class.isInstance(oldValue)) {  
  16.                         //减少缓存计数  
  17.                         ((RecyclingBitmapDrawable) oldValue).setIsCached(false);  
  18.                     } else {  
  19.                         //加入待重用集合  
  20.                         if (Build.VERSION.SDK_INT >= VERSION_CODES.HONEYCOMB) {  
  21.                             mReusableBitmaps.add(new SoftReference<Bitmap>(oldValue.getBitmap()));  
  22.                         }  
  23.                     }  
  24.                 }  
  25.   
  26.                 @Override  
  27.                 protected int sizeOf(String key, BitmapDrawable bitmapDrawable) {  
  28.                     final int bitmapSize = getBitmapSize(bitmapDrawable) / 1024;  
  29.                     return bitmapSize == 0 ? 1 : bitmapSize;  
  30.                 }  
  31.                   
  32.             };  
  33.         }  
  34.     }  
方法的开始,对当前Android版本进行了判断,如果是3.0以上,则初始化 mReusableBitmaps。在entryRemoved中,如果是3.0以上,将从缓存中移出的 Bitmap加入集合。

在方法中,decoder去检查是否有可用的bitmap。

[java] view plaincopy
  1. public static Bitmap decodeSampledBitmapFromStream(InputStream is,  
  2.         BitmapFactory.Options options, ImageCache cache) {  
  3.   
  4.     if (Build.VERSION.SDK_INT >= VERSION_CODES.HONEYCOMB) {  
  5.         addInBitmapOptions(options, cache);  
  6.     }  
  7.   
  8.     return BitmapFactory.decodeStream(is, null, options);  
  9. }  

addInBitmapOptions方法会去可重用的集合中查找一个合适的bitmap赋值给inBitmap,这个方法不保证一定返回非空的bitmap

[java] view plaincopy
  1. @TargetApi(Build.VERSION_CODES.HONEYCOMB)  
  2. private static void addInBitmapOptions(BitmapFactory.Options options,  
  3.         ImageCache cache) {  
  4.   
  5.     options.inMutable = true;  
  6.     if (cache != null) {  
  7.         Bitmap inBitmap = cache.getBitmapFromReusableSet(options);  
  8.   
  9.         if (inBitmap != null) {  
  10.             options.inBitmap = inBitmap;  
  11.         }  
  12.     }  
  13. }  

getBitmapFromReusableSet方法中,遍历集合中的每个Bitmap,如果有合适的就返回。

[java] view plaincopy
  1. protected Bitmap getBitmapFromReusableSet(BitmapFactory.Options options) {  
  2.     Bitmap bitmap = null;  
  3.   
  4.     if (mReusableBitmaps != null && !mReusableBitmaps.isEmpty()) {  
  5.         final Iterator<SoftReference<Bitmap>> iterator = mReusableBitmaps  
  6.                 .iterator();  
  7.         Bitmap item;  
  8.   
  9.         while (iterator.hasNext()) {  
  10.             item = iterator.next().get();  
  11.   
  12.             if (null != item && item.isMutable()) {  
  13.                 if (canUseForInBitmap(item, options)) {  
  14.                     bitmap = item;  
  15.   
  16.                     // Remove from reusable set so it can't be used again  
  17.                     iterator.remove();  
  18.                     break;  
  19.                 }  
  20.             } else {  
  21.                 // Remove from the set if the reference has been cleared.  
  22.                 iterator.remove();  
  23.             }  
  24.         }  
  25.     }  
  26.   
  27.     return bitmap;  
  28. }  

[java] view plaincopy
  1. @TargetApi(VERSION_CODES.KITKAT)  
  2. private static boolean canUseForInBitmap(Bitmap candidate,  
  3.         BitmapFactory.Options targetOptions) {  
  4.   
  5.     // 4.4之前的版本,尺寸必须完全吻合  
  6.     if (Build.VERSION.SDK_INT < VERSION_CODES.KITKAT) {  
  7.         return candidate.getWidth() == targetOptions.outWidth  
  8.                 && candidate.getHeight() == targetOptions.outHeight  
  9.                 && targetOptions.inSampleSize == 1;  
  10.     }  
  11.     // 4.4版本,可以使用比自己大的bitmap  
  12.     int width = targetOptions.outWidth / targetOptions.inSampleSize;  
  13.     int height = targetOptions.outHeight / targetOptions.inSampleSize;  
  14.   
  15.     // 根据图片格式,计算具体的bitmap大小  
  16.     int byteCount = width * height  
  17.             * getBytesPerPixel(candidate.getConfig());  
  18.   
  19.     return byteCount <= candidate.getAllocationByteCount();  
  20. }  
  21.   
  22. /** 
  23.  * Return the byte usage per pixel of a bitmap based on its configuration. 
  24.  *  
  25.  * @param config 
  26.  *            The bitmap configuration. 
  27.  * @return The byte usage per pixel. 
  28.  */  
  29. private static int getBytesPerPixel(Config config) {  
  30.     if (config == Config.ARGB_8888) {  
  31.         return 4;  
  32.     } else if (config == Config.RGB_565) {  
  33.         return 2;  
  34.     } else if (config == Config.ARGB_4444) {  
  35.         return 2;  
  36.     } else if (config == Config.ALPHA_8) {  
  37.         return 1;  
  38.     }  
  39.     return 1;  
  40. }  

完整的ImageCache代码:

@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2)public class ImageCache {private static final String TAG = "TEST";//缓存基本设置private static final int DEFAULT_MEM_CACHE_SIZE = 1024 * 5; // 内存缓存默认大小5MBprivate static final boolean DEFAULT_MEM_CACHE_ENABLED = true;//内存缓存private LruCache<String, BitmapDrawable> mMemoryCache;private ImageCacheParams mCacheParams;//3.0后的bitmap重用机制private Set<SoftReference<Bitmap>> mReusableBitmaps;public static class ImageCacheParams {//mempublic int memCacheSize = DEFAULT_MEM_CACHE_SIZE;public boolean memoryCacheEnabled = DEFAULT_MEM_CACHE_ENABLED;/*** * 手动设置内存缓存大小 * @param percent 缓存大小占最大可用内存的比例 */public void setMemCacheSizePercent(float percent) {if (percent < 0.01f || percent > 0.8f) {throw new IllegalArgumentException("setMemCacheSizePercent - percent must be "+ "between 0.01 and 0.8 (inclusive)");}memCacheSize = Math.round(percent * Runtime.getRuntime().maxMemory() / 1024);}}protected Bitmap getBitmapFromReusableSet(BitmapFactory.Options options) {Bitmap bitmap = null;if (mReusableBitmaps != null && !mReusableBitmaps.isEmpty()) {final Iterator<SoftReference<Bitmap>> iterator = mReusableBitmaps.iterator();Bitmap item;while (iterator.hasNext()) {item = iterator.next().get();if (null != item && item.isMutable()) {if (canUseForInBitmap(item, options)) {Log.v("TEST", "canUseForInBitmap!!!!");                        bitmap = item;                        // Remove from reusable set so it can't be used again                        iterator.remove();                        break;                    }} else {// Remove from the set if the reference has been cleared.iterator.remove();}}}return bitmap;}@TargetApi(VERSION_CODES.KITKAT)private static boolean canUseForInBitmap(Bitmap candidate, BitmapFactory.Options targetOptions) {//4.4之前的版本,尺寸必须完全吻合if (Build.VERSION.SDK_INT < VERSION_CODES.KITKAT) {return candidate.getWidth() == targetOptions.outWidth                    && candidate.getHeight() == targetOptions.outHeight                    && targetOptions.inSampleSize == 1;}//4.4版本,可以使用比自己大的bitmapint width = targetOptions.outWidth / targetOptions.inSampleSize;int height = targetOptions.outHeight / targetOptions.inSampleSize;//根据图片格式,计算具体的bitmap大小int byteCount = width * height * getBytesPerPixel(candidate.getConfig());return byteCount <= candidate.getAllocationByteCount();}/**     * Return the byte usage per pixel of a bitmap based on its configuration.     * @param config The bitmap configuration.     * @return The byte usage per pixel.     */    private static int getBytesPerPixel(Config config) {        if (config == Config.ARGB_8888) {            return 4;        } else if (config == Config.RGB_565) {            return 2;        } else if (config == Config.ARGB_4444) {            return 2;        } else if (config == Config.ALPHA_8) {            return 1;        }        return 1;    }/** *  * 放在no UI的fragment中,保证屏幕旋转时不被回收 * @param fragmentManager * @param cacheParams * @return */public static ImageCache getInstance(FragmentManager fragmentManager, ImageCacheParams cacheParams) {final RetainFragment mRetainFragment = findOrCreateRetainFragment(fragmentManager);ImageCache imageCache = (ImageCache) mRetainFragment.getObject();if (imageCache == null) {            imageCache = new ImageCache(cacheParams);            mRetainFragment.setObject(imageCache);        }        return imageCache;}    private ImageCache(ImageCacheParams cacheParams) {        init(cacheParams);    }        private void init(ImageCacheParams cacheParams) {    mCacheParams = cacheParams;    if (mCacheParams.memoryCacheEnabled) {    //Android3.0以上可以重用bitmap内存,将内存缓存中的回收项重用。    if (Build.VERSION.SDK_INT >= VERSION_CODES.HONEYCOMB) {    mReusableBitmaps =                        Collections.synchronizedSet(new HashSet<SoftReference<Bitmap>>());    }        mMemoryCache = new LruCache<String, BitmapDrawable>(mCacheParams.memCacheSize) {@Overrideprotected void entryRemoved(boolean evicted, String key,BitmapDrawable oldValue, BitmapDrawable newValue) {if (RecyclingBitmapDrawable.class.isInstance(oldValue)) {//减少缓存计数((RecyclingBitmapDrawable) oldValue).setIsCached(false);} else {//加入待重用集合if (Build.VERSION.SDK_INT >= VERSION_CODES.HONEYCOMB) {mReusableBitmaps.add(new SoftReference<Bitmap>(oldValue.getBitmap()));}}}@Overrideprotected int sizeOf(String key, BitmapDrawable bitmapDrawable) {final int bitmapSize = getBitmapSize(bitmapDrawable) / 1024;return bitmapSize == 0 ? 1 : bitmapSize;}        };    }    }        /**     * 清空缓存     */    public void clearCache() {    if (mMemoryCache != null) {            mMemoryCache.evictAll();        }    }            /**     * 获取bitmap大小     * @param bitmapDrawable     * @return     */    @TargetApi(Build.VERSION_CODES.KITKAT)public static int getBitmapSize(BitmapDrawable bitmapDrawable) {        Bitmap bitmap = bitmapDrawable.getBitmap();    //4.4    if (Build.VERSION.SDK_INT >= VERSION_CODES.KITKAT) {    return bitmap.getAllocationByteCount();    }    //3.1及以上    if (Build.VERSION.SDK_INT >= VERSION_CODES.HONEYCOMB_MR1) {    return  bitmap.getByteCount();    }    //3.1之前的版本    return bitmap.getRowBytes() * bitmap.getHeight();    }        /**获取内存缓存中的图片     * @param url     * @return     */    public BitmapDrawable getBitmapFromMemCache(String url) {    BitmapDrawable bitmapDrawable = null;        if (mMemoryCache != null) {    bitmapDrawable = mMemoryCache.get(url);    }        if (bitmapDrawable != null) {            Log.d("TEST", "Memory cache hit");        }        return bitmapDrawable;    }        /**     * 图片加入内存缓存     * @param data     * @param value     */    public void addBitmapToCache(String url, BitmapDrawable bitmapDrawable) {    if (url == null || bitmapDrawable == null) {    return;    }        //先加入内存缓存    if (mMemoryCache != null) {    //如果是RecyclingBitmapDrawable,增加缓存计数    if (RecyclingBitmapDrawable.class.isInstance(bitmapDrawable)) {    ((RecyclingBitmapDrawable) bitmapDrawable).setIsCached(true);    }        mMemoryCache.put(url, bitmapDrawable);    }    }private static RetainFragment findOrCreateRetainFragment(FragmentManager fm) {RetainFragment mRetainFragment = (RetainFragment) fm.findFragmentByTag(ImageCache.class.getName());if (mRetainFragment == null) {mRetainFragment = new RetainFragment();fm.beginTransaction().add(mRetainFragment, ImageCache.class.getName()).commitAllowingStateLoss();;}return mRetainFragment;}/** * 后台Fragment用于在横竖屏切换时保存ImageCache对象。 * */public static class RetainFragment extends Fragment {private Object object;public Object getObject() {return object;}public void setObject(Object object) {this.object = object;}@Override        public void onCreate(Bundle savedInstanceState) {            super.onCreate(savedInstanceState);            setRetainInstance(true);        }}}

Demo下载地址:

http://download.csdn.net/detail/ohehehou/8137871
0 0
原创粉丝点击