读书人

Android进阶练习 - 高效显示Bit地图(

发布时间: 2013-04-09 16:45:09 作者: rapoo

Android进阶练习 - 高效显示Bitmap(管理Bitmap内存)

管理Bitmap内存
除了在前面几篇文章中提到的缓存图片的步骤外,还有一些事情需要做来促进垃圾回收和位图的重用。Android目标版本决定了我们将使用什么策略。
先来看看Android不同版本对Bitmap管理的进化
在Android2.2或更低的版本中,当出现垃圾回收时,你的应用会暂停执行。这会导致延迟,降低程序性能。Android2.3增加了并行的垃 圾回收机制,这意味着当图片对象不再被引用时所占用的内存空间马上会被回收利用
在Android2.3或更低版本中,图片的像素级数据是存储在本地内存(JVM 用于其内部操作的内存)中的,它和Bitmap对象本身是分开来的,Bitmap对象本身是存储在Java虚拟机堆中。在本地内存中的像素数据的释放是不可预知的,这样就有可能会导致应用短暂的超过内存限制,从而程序崩溃。Android3.0之后,Bitmap像素数据和它本身都存储在Java虚拟机的堆内存中
下面我们来看看在不同的Android版本中如何来对Bitmap内存进行管理
Android2.3或更低版本中对Bitmap内存的管理 在Android2.3或更低版本中,推荐对Bitmap使用recycle() 方法。如果你在你的一个用中显示大量的图片数据,那么你的应用非常有可能出现OutOfMemoryError 错误。调用 recycle() 方法能让应用以尽可能快的回收Bitmap所占用的内存资源。 警告:你应该调用 recycle() 方法的时机是:当你不会再使用这张Bitmap。如果你后续再试图去访问,你将会得到"Canvas: trying to use a recycled bitmap" 错误
下面的程序片段是调用recycle() 示例,使用到了引用计数(mDisplayRefCount and mCacheRefCount)来追踪一张Bitmap是正在被显示还是存储在缓存中,回收Bitmap需要符合以下两个条件 1、 mDisplayRefCount and mCacheRefCount 的引用计数都为0 2、Bitmap对象不为null,并且没有被回收

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 属性。 如果设置了这个属性,那么使用了Options 对象作为参数的decode方法会试图重用现有的Bitmap来作为方法的返回值。 这意味着Bitmap的内存资源被重用了,从而使得程序性能得到提高,并且消除了这份内存的分配和回收工作。下面是使用inBitmap 属性的一些说明和注意点 要进行重用的Bitmap的大小必须要跟源图片大小一致(确保两者内存使用大小一样),而且图片必须是PNG或JPEG格式(可以是资源,也可以是二进制流数据) 如果源图片设置了inPreferredConfig 配置项,那么要进行重用的Bitmap也设置此项 你应该一值使用decode方法返回的Bitmap,因为我们不能保证重用的Bitmap是否可靠(比如,上面提到的大小有可能不匹配)
保存一张Bitmap供以后使用
在Android3.0或更高版本上,当一张Bitmap被LruCache 踢出时,Bitmap的软引用会被保存在一个HashSet中 ,可能稍后会被inBitmap 使用。
读书人网 >Android

热点推荐