面试的时候你会遇到很多的问题,这些问题可能会把你难住,这恰恰是你平常没有注意到的细节或者知识点,回来后就可以针对这些方面进行学习提高。
在一次面试的时候,面试官问我关于 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() 的运行机制。