美文网首页Android精品集合
Bitmap.recycle引发的血案

Bitmap.recycle引发的血案

作者: ChineseBoy | 来源:发表于2017-07-20 17:39 被阅读8次

    在Android中,Bitmap的存储分为两部分,一部分是Bitmap的数据,一部分是Bitmap的引用。
    在Android2.3时代,Bitmap的引用是放在堆中的,而Bitmap的数据部分是放在栈中的,需要用户调用recycle方法手动进行内存回收,而在Android2.3之后,整个Bitmap,包括数据和引用,都放在了堆中,这样,整个Bitmap的回收就全部交给GC了,这个recycle方法就再也不需要使用了。

    真的,一定不能再用了啊啊啊啊啊。。。。。。。。。。。

    现在的SDK中对recycle方法是这样注释的,可以发现,[系统]建议你不要手动去调用,而是让GC来进行处理不再使用的Bitmap。我们可以认为,即使在Android2.3之后的版本中去调用recycle,系统也是会强制回收内存的,只是系统不建议这样做而已。

    这个bug的起因是因为我们的一张图片需要旋转,同时可以设置一个旋转角度,老的代码是这样写的:

    public static Bitmap rotateBitmap(Bitmap sourceBitmap, int degress, boolean frontCamera) {
            Matrix matrix = new Matrix();
            matrix.postRotate(degress);
            if (frontCamera) {
                if (degress == 90 || degress == 270) {
                    matrix.postScale(1, -1);
                } else {
                    matrix.postScale(-1, 1);
                }
            }
            Bitmap rotaBitmap = Bitmap.createBitmap(sourceBitmap, 0, 0, sourceBitmap.getWidth(), sourceBitmap.getHeight(), matrix, false);
            return rotaBitmap;
        }
    

    从上面的代码可以很明显的看到我是新create了一个 “新” Bitmap,但是真的新么,不见得啊!!!
    按道理来说,bitmap与create出来的rotaBitmap应该是两个对象,当旋转角度正常的时候,确实也是这样,但当旋转角度比较奇葩的时候(这里我旋转了0度),这两个bitmap对象居然变成了同一个!而打开Bitmap.createBitmap的代码,可以发现如下所示的注释:

    image.png

    The new bitmap may be the same object as source, or a copy may have been made. It is initialized with the same density as the original bitmap.
    可能为同一个Bitmap!!!google为了省内存真是666了

    当图像的旋转角度小余两个像素点之间的夹角时,图像即使选择也无法显示,因此,系统完全可以认为图像没有发生变化,因此,注释中的情况,就是这种情况了。

    血泪史,2.3后不要在用recycle来干事了,GC不是吃屎的。

    相关文章

      网友评论

        本文标题:Bitmap.recycle引发的血案

        本文链接:https://www.haomeiwen.com/subject/qldjkxtx.html