2

实际上我在我的应用程序中面临内存不足错误。:(问题是我一直在我的应用程序中使用活动数量,现在我无法转向另一种方法..:(所以在翻转 27 或29 个活动我在 setContentView() 上的 30 个活动上遇到 OOM 错误。在我的所有 XML 文件中,我一直在使用 AbsoluteLayout 设置背景图像,每个布局都有一个主页。在每个布局中,我都设置了 4 到 5 个背景按钮image. 现在每个按钮都设置有声音的图像。

4

3 回答 3

4

我发现开发 Android 应用程序的最常见错误之一是“java.lang.OutOfMemoryError: Bitmap Size Exceeds VM Budget”错误。我在更改方向后使用大量位图的活动上经常发现此错误:活动被销毁,再次创建,布局从 XML 中“膨胀”,消耗了位图可用的 VM 内存。

垃圾收集器未正确释放先前活动布局上的位图,因为它们已交叉引用其活动。经过多次实验,我找到了一个很好的解决这个问题的方法。

首先,在 XML 布局的父视图上设置“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() 方法,将引用传递给父视图,然后执行 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() 方法递归地探索视图树并且:

Removes callbacks on all the background drawables
Removes childs on every viewgroup

这个解决方案对我有用

于 2012-09-28T11:41:50.073 回答
2

我建议使用system.gc()并且finish();每次跳转另一个活动它会清除您使用的资源并释放它。好的,那么您的应用程序中不会发生内存不足错误。这是工作试试这个。

祝你好运

使用此链接并获得更好的解决方案

哪些 Android 工具和方法最适合查找内存/资源泄漏?

于 2012-09-28T11:13:58.067 回答
0

我一直在没有大量 RAM (HTC Wildfire) 的 Gingerbread (2.3.7) 设备上解决这个问题。旋转设备几次后,应用程序崩溃:

E/AndroidRuntime( 4805): Caused by: java.lang.OutOfMemoryError: bitmap size exceeds VM budget
E/AndroidRuntime( 4805):        at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method)
E/AndroidRuntime( 4805):        at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:460)
E/AndroidRuntime( 4805):        at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:336)
E/AndroidRuntime( 4805):        at android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:697)
E/AndroidRuntime( 4805):        at android.content.res.Resources.loadDrawable(Resources.java:1785)
E/AndroidRuntime( 4805):        at android.content.res.TypedArray.getDrawable(TypedArray.java:601)
E/AndroidRuntime( 4805):        at android.widget.ImageView.<init>(ImageView.java:118)
E/AndroidRuntime( 4805):        at android.widget.ImageView.<init>(ImageView.java:108)
E/AndroidRuntime( 4805):        ... 26 more

旋转的布局非常简单,RelativeLayout有几个ImageView孩子,其中一个有一个相对较大(文件大小)的图像作为屏幕一部分的背景。

我尝试实施@AndroidUsers 的解决方案,但这并没有解决我的问题。通过更多的工作,我发现我保存背景图像的 ImageView 没有正确释放它的内存,所以我在 unbindDrawables 方法中添加了另一个检查。我还通过一个额外的参数捆绑在 system.gc() 调用中,因此不能错过:

public static void unbindDrawables(View view, boolean runGC) {
    if (view.getBackground() != null) {
        view.getBackground().setCallback(null);
    }

    if (view instanceof ImageView) {
        ((ImageView) view).setImageBitmap(null);
        ((ImageView) view).setImageDrawable(null);
    }
    else if (view instanceof ViewGroup) {
        for (int i = 0; i < ((ViewGroup) view).getChildCount(); i++) {
            unbindDrawables(((ViewGroup) view).getChildAt(i), false);
        }
        ((ViewGroup) view).removeAllViews();
    }

    if(runGC) {
        System.gc();
    }
}

在我的测试中,您将 Bi​​tmap 或 Drawable 中的哪一个设置为 null 似乎并不重要,但我认为两者都不会受到伤害。

于 2014-08-15T01:38:06.753 回答