Bitmap recycle() 源码解析

面试的时候你会遇到很多的问题,这些问题可能会把你难住,这恰恰是你平常没有注意到的细节或者知识点,回来后就可以针对这些方面进行学习提高。

在一次面试的时候,面试官问我关于 OOM 的问题,这很常见,也没有难住我,在我阐述了我的观点后,面试官又开始对这一方面进行深入的提问(面试官往往会从一点基础常见的问题开始,慢慢深入,来了解你的水平)。接下来他又问了我 OOM 中常见的 Bitmap 处理,这个比刚刚的问题深入了些,但是也在正常范围内,我又回答了他,主要是 Bitmap 转换的流的处理。之后他又对我回答的流的recycle() 方法进行提问,问我 recycle() 方法他的运行机制,这个就涉及到源码方面了。这个直接把我问住了,平常的开发中一般都是到 调用 recycle() 为止,还真没有点进去看下 recycle() 的机制。回来后赶紧点进去看了看,原来是这么回事。

/**
 * Free the native object associated with this bitmap, and clear the
 * reference to the pixel data. This will not free the pixel data synchronously;
 * it simply allows it to be garbage collected if there are no other references.
 * The bitmap is marked as "dead", meaning it will throw an exception if
 * getPixels() or setPixels() is called, and will draw nothing. This operation
 * cannot be reversed, so it should only be called if you are sure there are no
 * further uses for the bitmap. This is an advanced call, and normally need
 * not be called, since the normal GC process will free up this memory when
 * there are no more references to this bitmap.
 * 
 *  释放被bitmap关联的本地内存,并且清除像素数据的引用。这个过程不会同步释放像素数据;
 *  它只是提醒 garbage 如果没有其他引用,那么它将会被其回收
 *  这张 bitmap 将会被标记 “dead” ,意味着当它在被调用 getPixels() 或setPixels()时会抛出异常。
 *  这个操作不能被撤销,所以只有当确认这个 bitmap 不会被再次引用的时候按此可以执行此操作
 *  这时一个高级方法,通常不需要主动调用它,因为当这个bitmap不会再次被引用时, GC会主动回收掉它并释放其内存
 */
public void recycle() {
    if (!mRecycled && mFinalizer.mNativeBitmap != 0) {
        if (nativeRecycle(mFinalizer.mNativeBitmap)) {
            // return value indicates whether native pixel object was actually recycled.
            // false indicates that it is still in use at the native level and these 
            // objects should not be collected now. They will be collected later when the
            // Bitmap itself is collected.

             //返回值表示是否本地像素对象是否被回收
             // false 表明它在本地仍在使用
            // 那些对象不会被立刻回收。他们将在被应用完之后被回收
            mBuffer = null;
            mNinePatchChunk = null;
        }
        mRecycled = true;
    }
}

这就是recycle() ,代码不多,就几行,我们一行行的来看下。
首先是第一重判断,这句判断主要是判别两个条件:
1. mRecycled 全局搜索下可以知道这是是否回收的标记值:

/**
 * Returns true if this bitmap has been recycled. If so, then it is an error
 * to try to access its pixels, and the bitmap will not draw.
 *
 * @return true if the bitmap has been recycled
 *  如果 bitmap 已经被回收过将会返回 true
 */
public final boolean isRecycled() {
    return mRecycled;
}

当调用多 recycle() 后这个标记值就会被置为 true,防止对一个对象进行多次recycle().

2.mFinalizer.mNativeBitmap 是否为0,这个参数点进去看下,我猜测他是bitmap的原始内存存储数组。

接下来是第二重判断:
nativeRecycle(),这是一个native 方法,同样作用是判断是否被回收了(关于这个 native 类型的方法具体要看Java,我也不是太懂)

private static native boolean nativeRecycle(long nativeBitmap);

如果两重判断都显示未进行回收过,那么久开始执行回收,将 mBuffer 置为空,mBuffer的注释是 Backing buffer for the Bitmap ,即是它的缓存,

/**
 * Backing buffer for the Bitmap.
 */
private byte[] mBuffer;

并且将mNinePatchChunk 置为空,这个参数我没有找到它的注释,但是从它的字面意思上来看,它应该是 .9 的格式缓存数组,当然他也有一句注释,it may be null :

private byte[] mNinePatchChunk; // may be null

也就是说它有可能是为空的,看来并不是所有情况下都会给他赋值,当然为了保险起见还是将其置为空。
最后,将recycle() 的标记值置为true,意为已经进行过回收了。以上就是recycle() 的运行机制。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值