您的位置:首页 > 其它

Bitmap处理之创建可自动回收资源的ImageView

2013-04-22 23:18 471 查看

1.创建可自动回收资源的BitmapDrawable

继承BitmapDrawable,设置标志位 mCacheRefCount cache计数,mDisplayRefCount 显示计数,mHasBeenDisplayed判断是否已经显示过了具体的code:

private int mCacheRefCount = 0;  //cache计数
private int mDisplayRefCount = 0; //显示计数

private boolean mHasBeenDisplayed;//是否已经显示过


判断bitmap是否还存在并且可用

private synchronized boolean hasValidBitmap() {
Bitmap bitmap = getBitmap();
return bitmap != null && !bitmap.isRecycled();
}


判断bitmap的状态

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();
}
}


通过cache计数,显示计数,是否已经显示,以及bitmap是否还存在,如果四个条件都满足,就显式的回收bitmap资源

判断bitmap是否已经cache

public void setIsCached(boolean isCached) {
synchronized (this) {
if (isCached) {
mCacheRefCount++;
} else {
mCacheRefCount--;
}
}

// Check to see if recycle() can be called
checkState();
}


调用的地方是,如果已经将某个bitmap加入了cache(memory cache,disk cache)setIsCached(true)这时cache计数就会增加1,如果某个bitmap从cache中删除,就setIsCached(false)这时cache计数就减去1,然后调用checkState()方法,来判断bitmap是否需要回收

判断bitmap是否已经显示

public void setIsDisplayed(boolean isDisplayed) {
synchronized (this) {
if (isDisplayed) {
mDisplayRefCount++;
mHasBeenDisplayed = true;
} else {
mDisplayRefCount--;
}
}

// Check to see if recycle() can be called
checkState();
}

完整的代码

public class RecyclingBitmapDrawable extends BitmapDrawable {

static final String LOG_TAG = "CountingBitmapDrawable";

private int mCacheRefCount = 0;
private int mDisplayRefCount = 0;

private boolean mHasBeenDisplayed;

public RecyclingBitmapDrawable(Resources res, Bitmap bitmap) {
super(res, bitmap);
}

/**
* Notify the drawable that the displayed state has changed. Internally a
* count is kept so that the drawable knows when it is no longer being
* displayed.
*
* @param isDisplayed - Whether the drawable is being displayed or not
*/
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. Internally a count
* is kept so that the drawable knows when it is no longer being cached.
*
* @param isCached - Whether the drawable is being cached or not
*/
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()) {
if (BuildConfig.DEBUG) {
Log.d(LOG_TAG, "No longer being used or cached so recycling. "
+ toString());
}

getBitmap().recycle();
}
}

private synchronized boolean hasValidBitmap() {
Bitmap bitmap = getBitmap();
return bitmap != null && !bitmap.isRecycled();
}

}


2.创建可自动回收资源的ImageView

基于RecyclingBitmapDrawable来实现 RecyclingImageView

具体实现

重载Imageiew的setImageDrawable()方法

public void setImageDrawable(Drawable drawable) {
// Keep hold of previous Drawable
final Drawable previousDrawable = getDrawable();

// Call super to set new Drawable
super.setImageDrawable(drawable);

// Notify new Drawable that it is being displayed
notifyDrawable(drawable, true);

// Notify old Drawable so it is no longer being displayed
notifyDrawable(previousDrawable, false);
}
在设置时,显获得前一个drawable资源,然后发出通知,通知的是实现

private static void notifyDrawable(Drawable drawable, final boolean isDisplayed) {
if (drawable instanceof RecyclingBitmapDrawable) {
// The drawable is a CountingBitmapDrawable, so notify it
((RecyclingBitmapDrawable) drawable).setIsDisplayed(isDisplayed);
} else if (drawable instanceof LayerDrawable) {
// The drawable is a LayerDrawable, so recurse on each layer
LayerDrawable layerDrawable = (LayerDrawable) drawable;
for (int i = 0, z = layerDrawable.getNumberOfLayers(); i < z; i++) {
notifyDrawable(layerDrawable.getDrawable(i), isDisplayed);
}
}
}
主要是调用RecyclingBitmapDrawable的setIsDisplayed方法,在通过ImageView设置时,当前的Drawable的显示计数加1,而前一个Drawable资源的显示计数减1,然后检查状态,这样前一个Drawable资源就有可能被回收

http://developer.android.com/training/displaying-bitmaps/process-bitmap.html#concurrency
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: