赞
踩
注:1.在Android2.2(API level 8)之前,当垃圾回收线程工作时,主线程会阻塞,这就造成了不好的用户体验,
所以在以后的版本中,出现了并发执行的垃圾回收线程,这意味着当一个Bitmap没有被引用时,就会被回收;2.在Android2.3.3(API level 10)之前,Bitmap的像素数据是存储在本地内存中,且与Bitmap本身是分开存储的,
(Bitmap存储在Dalvik虚拟机的堆内存中)。在Android3.0(API level 11)版本之后,两者都存储在虚拟机堆内存中。一、管理Android2.3.3之前版本设备的Bitmap存储
建议使用recycle()方法回收空间,应该在Bitmap对象不再被使用了调用该方法。如果已经recycle后尝试使用该Bitmap,会得到如下错误: "Canvas: trying to use a recycled bitmap".
- private int mCacheRefCount = 0;
- private int mDisplayRefCount = 0;
- ...
- // Notify the drawable that the displayed state has changed.
- // Keep a count to determine when the drawable is no longer displayed.
- public void setIsDisplayed(boolean isDisplayed) {
- synchronized (this) {
- if (isDisplayed) {
- mDisplayRefCount++;
- mHasBeenDisplayed = true;
- } else {
- mDisplayRefCount--;
- }
- }
- // Check to see if recycle() can be called.
- checkState();
- }
-
- // Notify the drawable that the cache state has changed.
- // Keep a count to determine when the drawable is no longer being cached.
- public void setIsCached(boolean isCached) {
- synchronized (this) {
- if (isCached) {
- mCacheRefCount++;
- } else {
- mCacheRefCount--;
- }
- }
- // Check to see if recycle() can be called.
- checkState();
- }
-
- private synchronized void checkState() {
- // If the drawable cache and display ref counts = 0, and this drawable
- // has been displayed, then recycle.
- if (mCacheRefCount <= 0 && mDisplayRefCount <= 0 && mHasBeenDisplayed
- && hasValidBitmap()) {
- getBitmap().recycle();
- }
- }
-
- private synchronized boolean hasValidBitmap() {
- Bitmap bitmap = getBitmap();
- return bitmap != null && !bitmap.isRecycled();
- }
二、在Android3.0版本之后的设备上管理Bitmap存储空间
Android3.0版本介绍了 BitmapFactory.Options.inBitmap字段,如果给该字段赋值,则在解码时会尝试
使用这个已存在的Bitmap对象,这意味着该Bitmap的存储空间被重复利用了。但是在Android4.4(API level 19)之前,只有尺寸一样的Bitmap才能被复用。
1.保存不再缓存的Bitmap引用
- Set<SoftReference<Bitmap>> mReusableBitmaps;
- private LruCache<String, BitmapDrawable> mMemoryCache;
-
- // If you're running on Honeycomb or newer, create a
- // synchronized HashSet of references to reusable bitmaps.
- if (Utils.hasHoneycomb()) {
- mReusableBitmaps =
- Collections.synchronizedSet(new HashSet<SoftReference<Bitmap>>());
- }
-
- mMemoryCache = new LruCache<String, BitmapDrawable>(mCacheParams.memCacheSize) {
-
- // Notify the removed entry that is no longer being cached.
- @Override
- protected void entryRemoved(boolean evicted, String key,
- BitmapDrawable oldValue, BitmapDrawable newValue) {
- if (RecyclingBitmapDrawable.class.isInstance(oldValue)) {
- // The removed entry is a recycling drawable, so notify it
- // that it has been removed from the memory cache.
- ((RecyclingBitmapDrawable) oldValue).setIsCached(false);
- } else {
- // The removed entry is a standard BitmapDrawable.
- if (Utils.hasHoneycomb()) {
- // We're running on Honeycomb or later, so add the bitmap
- // to a SoftReference set for possible use with inBitmap later.
- mReusableBitmaps.add
- (new SoftReference<Bitmap>(oldValue.getBitmap()));
- }
- }
- }
- ....
- }
2.尝试使用已经存在的Bitmap对象:
- public static Bitmap decodeSampledBitmapFromFile(String filename,
- int reqWidth, int reqHeight, ImageCache cache) {
-
- final BitmapFactory.Options options = new BitmapFactory.Options();
- ...
- BitmapFactory.decodeFile(filename, options);
- ...
-
- // If we're running on Honeycomb or newer, try to use inBitmap.
- if (Utils.hasHoneycomb()) {
- addInBitmapOptions(options, cache);
- }
- ...
- return BitmapFactory.decodeFile(filename, options);
- }
3.给option添加inBitmap属性值:
- private static void addInBitmapOptions(BitmapFactory.Options options,
- ImageCache cache) {
- // inBitmap only works with mutable bitmaps, so force the decoder to
- // return mutable bitmaps.
- options.inMutable = true;
-
- if (cache != null) {
- // Try to find a bitmap to use for inBitmap.
- Bitmap inBitmap = cache.getBitmapFromReusableSet(options);
-
- if (inBitmap != null) {
- // If a suitable bitmap has been found, set it as the value of
- // inBitmap.
- options.inBitmap = inBitmap;
- }
- }
- }
4.从保存的Bitmap引用中寻找合适的Bitmap对象:
- // This method iterates through the reusable bitmaps, looking for one
- // to use for inBitmap:
- protected Bitmap getBitmapFromReusableSet(BitmapFactory.Options options) {
- Bitmap bitmap = null;
-
- if (mReusableBitmaps != null && !mReusableBitmaps.isEmpty()) {
- synchronized (mReusableBitmaps) {
- final Iterator<SoftReference<Bitmap>> iterator
- = mReusableBitmaps.iterator();
- Bitmap item;
-
- while (iterator.hasNext()) {
- item = iterator.next().get();
-
- if (null != item && item.isMutable()) {
- // Check to see it the item can be used for inBitmap.
- if (canUseForInBitmap(item, options)) {
- 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;
- }
5.判断当前Bitmap是否可用:
- static boolean canUseForInBitmap(
- Bitmap candidate, BitmapFactory.Options targetOptions) {
-
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
- // From Android 4.4 (KitKat) onward we can re-use if the byte size of
- // the new bitmap is smaller than the reusable bitmap candidate
- // allocation byte count.
- int width = targetOptions.outWidth / targetOptions.inSampleSize;
- int height = targetOptions.outHeight / targetOptions.inSampleSize;
- int byteCount = width * height * getBytesPerPixel(candidate.getConfig());
- return byteCount <= candidate.getAllocationByteCount();
- }
-
- // On earlier versions, the dimensions must match exactly and the inSampleSize must be 1
- return candidate.getWidth() == targetOptions.outWidth
- && candidate.getHeight() == targetOptions.outHeight
- && targetOptions.inSampleSize == 1;
- }
-
- /**
- * A helper function to return the byte usage per pixel of a bitmap based on its configuration.
- */
- 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;
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。