我在 Android 上开发了一个使用大量图像的应用程序。
应用程序运行一次,填充屏幕上的信息(Layouts
、Listviews
、Textviews
、ImageViews
等),用户读取信息。
没有动画,没有特效或者任何可以填满内存的东西。 有时绘图可能会改变。有些是android资源,有些是保存在SDCARD文件夹中的文件。
然后用户退出(执行 onDestroy
方法,并且应用程序由虚拟机保留在内存中),然后在某个时刻用户再次进入。
每次用户进入应用程序时,我都可以看到内存越来越多,直到用户收到 java.lang.OutOfMemoryError
。
那么处理许多图像的最佳/正确方法是什么?
我应该将它们放在静态方法中,这样它们就不会一直加载吗? 我是否必须以特殊方式清理布局或布局中使用的图像?
最佳答案
我发现开发 Android 应用程序时最常见的错误之一是“java.lang.OutOfMemoryError:位图大小超出 VM 预算”错误。在更改方向后,我经常在使用大量位图的 Activity 中发现此错误: Activity 被销毁,再次创建,并且布局因消耗可用于位图的 VM 内存的 XML 而“膨胀”。
垃圾收集器未正确取消分配先前 Activity 布局上的位图,因为它们交叉引用了其 Activity 。经过多次实验,我找到了一个很好的解决这个问题的方法。
首先,在 XML 布局的父 View 上设置“id”属性:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="@+id/RootView"
>
...
然后,在 Activity 的 onDestroy()
方法上,调用 unbindDrawables()
方法,传递对父 View 的引用,然后执行 System .gc()
.
@Override
protected void onDestroy() {
super.onDestroy();
unbindDrawables(findViewById(R.id.RootView));
System.gc();
}
private void unbindDrawables(View view) {
if (view.getBackground() != null) {
view.getBackground().setCallback(null);
}
if (view instanceof ViewGroup) {
for (int i = 0; i < ((ViewGroup) view).getChildCount(); i++) {
unbindDrawables(((ViewGroup) view).getChildAt(i));
}
((ViewGroup) view).removeAllViews();
}
}
这个unbindDrawables()
方法递归地探索 View 树并且:
- 删除所有背景可绘制对象上的回调
- 删除每个 View 组上的子级
关于android - java.lang.OutOfMemory错误: bitmap size exceeds VM budget - Android,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29104063/