博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Bitmap处理之创建可自动回收资源的ImageView
阅读量:6608 次
发布时间:2019-06-24

本文共 5140 字,大约阅读时间需要 17 分钟。

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://zwiso.baihongyu.com/

你可能感兴趣的文章
004 ps基础裁剪照片,制作大头贴
查看>>
gtid环境下mysqldump对于set-gtid-purged的取值
查看>>
最好吃的水果是猕猴桃
查看>>
Kerberos和NTLM - SQL Server
查看>>
错误信息输出,重定向到文件
查看>>
修改Oracle Client的字符集
查看>>
django中的权限控制(form增删改)
查看>>
STL学习笔记--非变易算法
查看>>
mysql设置字符集CHARACTER SET
查看>>
redis 系列15 数据对象的(类型检查,内存回收,对象共享)和数据库切换
查看>>
log框架集成
查看>>
python命令行下安装redis客户端
查看>>
如何在Oracle中复制表结构和表数据
查看>>
[河南省ACM省赛-第四届] 序号互换 (nyoj 303)
查看>>
SICIP-1.3-Defining a new function
查看>>
3 Oracle 32位客户端安装及arcgis连接
查看>>
scala2.12.5在windows10、osmac10.13上的安装
查看>>
转自老叶茶馆]系列 — processlist中哪些状态要引起关注
查看>>
小程序上拉加载的坑
查看>>
c++强制类型转换(总结)
查看>>