【问题标题】:Only Android 4.1, Bitmap is recycled automatically仅Android 4.1,Bitmap自动回收
【发布时间】:2012-10-05 03:11:58
【问题描述】:

我遇到了非常严重的问题。 只有Android 4.1,Bitmap会自动回收! 我没有在我的代码中调用 recycle() ! 我的项目在任何分辨率的其他操作系统版本(〜4.0.3)中都可以正常工作。 其他项目也有同样的问题。

所有图像文件都在 drawable-nodpi 文件夹中。 我总是调整它们的大小以适应任何设备的分辨率。

public Bitmap GetBitmap(int resource){

    BitmapFactory.Options options = new BitmapFactory.Options();
    options.inDither = true;
    options.inPurgeable = true;

    Bitmap tmp = null;

    try{
        tmp = BitmapFactory.decodeResource(mResources, resource, options);
    }catch(OutOfMemoryError e){
        options.inSampleSize = 2;
        tmp = BitmapFactory.decodeResource(mResources, resource, options);
    }

    return tmp;
}

public Bitmap GetScaledBitmap(int resource, int width, int height, boolean filter){

    Bitmap tmp = GetBitmap(resource);

    Bitmap img = Bitmap.createScaledBitmap(tmp, width, height, filter);

    tmp.recycle();
    tmp = null;

    return img;
}

在我的测试中,

  • 相同的位图实例,但根据调整大小会出现问题。

例如) 整数宽度 = 100;

位图 imgStar = MyResourceManager.getInstance().GetScaledBitmap(R.drawable.star, width, width , true); -> 返回回收的实例。

宽度 = 200;

imgStar = MyResourceManager.getInstance().GetScaledBitmap(R.drawable.star, width, width, true); -> 返回普通实例。

  • 在不同的分辨率下,imgStar 工作正常,但在其他位图实例中出现问题。 同样,当我更改调整大小时,它工作正常。

  • 在相同的分辨率下,如果我更改图像文件文件夹的名称,问题出现在其他位图实例中。 drawable-nodpi -> drawable -> drawable-ldpi, ..., drawable-xdpi.

  • 相同的大小调整值,如果我输入其他资源 ID,它可以正常工作。 例如)

int 宽度 = 100;

位图 imgStar = MyResourceManager.getInstance().GetScaledBitmap(R.drawable.star, width, width , true); -> 返回回收的实例。

imgStar = MyResourceManager.getInstance().GetScaledBitmap(R.drawable.diamond, width, width, true); -> 返回普通实例。

请……我该怎么办?! T^T

【问题讨论】:

标签: android bitmap drawable android-4.2-jelly-bean recycle


【解决方案1】:

您从不同大小得到不同结果的原因可能是因为 createScaledBitmap 将返回原始对象,如果它与您缩放到的大小相同。

我遇到了同样的问题,正在做同样的事情。我能够通过这种方式修复它:

public Bitmap GetScaledBitmap(int resource, int width, int height, boolean filter) {

    Bitmap tmp = GetBitmap(resource);
    Bitmap img = Bitmap.createScaledBitmap(tmp, width, height, filter);
    //copy the image to be sure you are not using the same object as the tmp bitmap
    img=img.copy (Bitmap.Config.RGB_565,false);
    tmp.recycle();
    tmp = null;
    return img;
}

在这里我复制了位图,以确保在回收 tmp 位图之前它不仅仅是对 tmp 位图对象的引用。当然你可以使用任何你需要的位图配置。

【讨论】:

    【解决方案2】:

    我相信 XdebugX 在他的发现中是正确的,尽管您不需要创建副本。只需检查调整大小的位图和原始位图之间的内存位置是否相同。

    public Bitmap GetScaledBitmap(int resource, int width, int height, boolean filter){
    
        Bitmap tmp = GetBitmap(resource);
        if (tmp == null) {
            return null;
        }
    
        Bitmap img = Bitmap.createScaledBitmap(tmp, width, height, filter);
    
        /***
         * Bitmap#createScaledBitmap will return the original object
         * if it is the same size you are scaling to.
         */
        if (tmp != img) {
            Log.d(TAG, "Full size image recycled");
            tmp.recycle();
        } else {
            Log.w(TAG, "Resized bitmap was the same as the fullsize bitmap");
        }
    
        return img;
    }
    

    【讨论】:

      【解决方案3】:

      我宁愿建议在回收之前尝试检查位图是否已经回收:

      if (!tmp.isRecycled()) tmp.recycle();
      

      【讨论】:

        猜你喜欢
        • 2019-09-05
        • 2011-10-23
        • 1970-01-01
        • 2011-07-16
        • 2023-03-19
        • 2014-12-30
        • 2016-05-24
        • 2016-06-15
        • 2011-08-07
        相关资源
        最近更新 更多