"Cannot draw recycled bitmaps" 如果我在 onDestroy() 中调用 recycle()

"Cannot draw recycled bitmaps" if I invoke recycle() inside onDestroy()

我有两个活动:MainActivityActivity2

MainActivity简单的通过Intent打开秒1

Activity2 到 return 到 MainActivity 我按下 "back" 按钮。

当我执行这些步骤时,应用程序崩溃:

MainActivity.java:

Intent intent = new Intent(this, Activity2.class);
startActivity(intent);

Activity2.java:

@Override
public void onBackPressed() {
    super.onBackPressed();
}

@Override
protected void onDestroy() {
    super.onDestroy();

    for(Map.Entry<Integer, ImageView> entry : mapImageViews.entrySet()) {
        ImageView imageView = entry.getValue();
        Drawable drawable = imageView.getDrawable();
        if (drawable instanceof BitmapDrawable) {
            BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable;
            Bitmap bitmap = bitmapDrawable.getBitmap();
            if(bitmap != null) {
                bitmap.recycle();
            }
            bitmapDrawable = null;
            bitmap = null;
        }
        imageView.setOnClickListener(null);
        imageView.setImageDrawable(null);
        imageView.setImageBitmap(null);
        imageView = null;
        drawable = null;
    }
    mapImageViews.clear();
    mapImageViews = null;
}

由于应用程序使用高分辨率图像(已经适应 BitmapFactoryinSampleSize),为了避免内存泄漏,我在 onDestroy() 方法中调用 recycle()

正如我通过阅读大量 SO 答案和在 Web 上了解到的那样,在位图上调用 recycle() 可以让它们尽早被垃圾回收。

但是许多其他帖子建议不要调用 recycle(),或者至少建议仅当您确定 Activity 中不再需要位图时才这样做,即在 onDestroy()方法。

现在我有点担心我学到的东西,因为如果我删除 recycle() 错误就不会再发生了。

错误发生在 Android 4.4.2 的设备上,但不会发生在 Android 6.0Nexus 7 的设备上( Android 5.1.1).

尝试改变您的 onDestroy 方法,如下所示

@Override
protected void onDestroy() {
    for(Map.Entry<Integer, ImageView> entry : mapImageViews.entrySet()) {
        ImageView imageView = entry.getValue();
        Drawable drawable = imageView.getDrawable();
        if (drawable instanceof BitmapDrawable) {
            BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable;
            Bitmap bitmap = bitmapDrawable.getBitmap();
            if(bitmap != null) {
                bitmap.recycle();
            }
            bitmapDrawable = null;
            bitmap = null;
        }
        imageView.setOnClickListener(null);
        imageView.setImageDrawable(null);
        imageView.setImageBitmap(null);
        imageView = null;
        drawable = null;
    }
    mapImageViews.clear();
    mapImageViews = null;

    super.onDestroy();
}

另请参阅:How to recycle and reuse images 以一种有效的方式。

根据回收文档

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.

我看不出你是如何将你的 bitmaps 分配给你的 ImageView,但我假设你在位图被 recycled.如果我使用 android:src=,我只会 运行 进入异常。如果我在 oncreate 中使用以下内容设置 ImageView 位图,它 运行 在您列出的所有目标上都很好,不会引发异常。

imageView.setImageBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.lake_park));

我强烈推荐使用 glide 来处理图像。 https://github.com/bumptech/glide

实际上我认为您不必手动执行此操作。

如果 Activity2 只有 1 张图像并且已经调整大小,我认为如果您真的遇到内存问题,回收也无济于事。

而且根据这篇文档只有API级别低于10才推荐使用recycle(),而且用户比例很小。 On Android 2.3.3 (API level 10) and lower, using recycle() is recommended. https://developer.android.com/topic/performance/graphics/manage-memory

而且我想推荐使用第三方图像库,因为它们可以让您摆脱这些无意义的事情,让您专注于应用中更重要的部分。