"Cannot draw recycled bitmaps" 如果我在 onDestroy() 中调用 recycle()
"Cannot draw recycled bitmaps" if I invoke recycle() inside onDestroy()
我有两个活动:MainActivity
和 Activity2
。
MainActivity简单的通过Intent打开秒1
从 Activity2
到 return 到 MainActivity
我按下 "back" 按钮。
当我执行这些步骤时,应用程序崩溃:
- 打开App:出现
MainActivity
- 启动 Intent:
Activity2
出现
- 按下"back"按钮:
MainActivity
出现
- 启动
Intent
:我的应用程序因为这个错误而崩溃:
IllegalArgumentException: Cannot draw recycled bitmaps
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;
}
由于应用程序使用高分辨率图像(已经适应 BitmapFactory
和 inSampleSize
),为了避免内存泄漏,我在 onDestroy()
方法中调用 recycle()
。
正如我通过阅读大量 SO 答案和在 Web 上了解到的那样,在位图上调用 recycle()
可以让它们尽早被垃圾回收。
但是许多其他帖子建议不要调用 recycle()
,或者至少建议仅当您确定 Activity 中不再需要位图时才这样做,即在 onDestroy()
方法。
现在我有点担心我学到的东西,因为如果我删除 recycle()
错误就不会再发生了。
错误发生在 Android 4.4.2
的设备上,但不会发生在 Android 6.0
和 Nexus 7
的设备上( Android 5.1.1
).
- 是活动堆栈的问题吗?
- GC 试图释放位图的内存是否为时已晚?在这种情况下,如何彻底销毁 Activity 及其所有内容?
- 这两个Android版本有什么区别吗?
- 或者我有什么东西missing/wrong?
尝试改变您的 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
而且我想推荐使用第三方图像库,因为它们可以让您摆脱这些无意义的事情,让您专注于应用中更重要的部分。
我有两个活动:MainActivity
和 Activity2
。
MainActivity简单的通过Intent打开秒1
从 Activity2
到 return 到 MainActivity
我按下 "back" 按钮。
当我执行这些步骤时,应用程序崩溃:
- 打开App:出现
MainActivity
- 启动 Intent:
Activity2
出现 - 按下"back"按钮:
MainActivity
出现 - 启动
Intent
:我的应用程序因为这个错误而崩溃:IllegalArgumentException: Cannot draw recycled bitmaps
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;
}
由于应用程序使用高分辨率图像(已经适应 BitmapFactory
和 inSampleSize
),为了避免内存泄漏,我在 onDestroy()
方法中调用 recycle()
。
正如我通过阅读大量 SO 答案和在 Web 上了解到的那样,在位图上调用 recycle()
可以让它们尽早被垃圾回收。
但是许多其他帖子建议不要调用 recycle()
,或者至少建议仅当您确定 Activity 中不再需要位图时才这样做,即在 onDestroy()
方法。
现在我有点担心我学到的东西,因为如果我删除 recycle()
错误就不会再发生了。
错误发生在 Android 4.4.2
的设备上,但不会发生在 Android 6.0
和 Nexus 7
的设备上( Android 5.1.1
).
- 是活动堆栈的问题吗?
- GC 试图释放位图的内存是否为时已晚?在这种情况下,如何彻底销毁 Activity 及其所有内容?
- 这两个Android版本有什么区别吗?
- 或者我有什么东西missing/wrong?
尝试改变您的 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
而且我想推荐使用第三方图像库,因为它们可以让您摆脱这些无意义的事情,让您专注于应用中更重要的部分。