27

在我的应用程序中,当我尝试启动它时强制关闭并且错误指向“setContentView(R.layout.Menu);”行 的布局。在 XML 文件中,它在我的布局中显示“OutOfMemoryError”图像视图。我真的很困惑。请指导我进一步行动。

编辑:

我的应用程序使用数据库,并在第一次解析一些 XML 数据并插入到 Sqlite 数据库中。我的内存不足问题仅在第一次出现。第二次它工作正常。我试过 System.gc()。有没有这方面的问题。

这是我的日志:

E/dalvikvm-heap(2712): 105376-byte external allocation too large for this process.
VM won't let us allocate 105376 bytes

    FATAL EXCEPTION: main
    java.lang.RuntimeException: Unable to start activity ComponentInfo{com.Test/com.Test.Menu}: android.view.InflateException: Binary XML file line #13: Error inflating class <unknown>
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1647)
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1663)
    at android.app.ActivityThread.access$1500(ActivityThread.java:117)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:931)
    at android.os.Handler.dispatchMessage(Handler.java:99)
    at android.os.Looper.loop(Looper.java:130)
    at android.app.ActivityThread.main(ActivityThread.java:3683)
    at java.lang.reflect.Method.invokeNative(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:507)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
    at dalvik.system.NativeStart.main(Native Method)
Caused by: android.view.InflateException: Binary XML file line #13: Error inflating class <unknown>
    at android.view.LayoutInflater.createView(LayoutInflater.java:518)
    at com.android.internal.policy.impl.PhoneLayoutInflater.onCreateView(PhoneLayoutInflater.java:56)
    at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:568)
    at android.view.LayoutInflater.rInflate(LayoutInflater.java:623)
    at android.view.LayoutInflater.rInflate(LayoutInflater.java:626)
    at android.view.LayoutInflater.inflate(LayoutInflater.java:408)
    at android.view.LayoutInflater.inflate(LayoutInflater.java:320)
    at android.view.LayoutInflater.inflate(LayoutInflater.java:276)
    at com.android.internal.policy.impl.PhoneWindow.setContentView(PhoneWindow.java:207)
    at android.app.Activity.setContentView(Activity.java:1657)
    at com.Test.Menu.onCreate(Menu.java:32)
    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1611)
    ... 11 more
Caused by: java.lang.reflect.InvocationTargetException
    at java.lang.reflect.Constructor.constructNative(Native Method)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:415)
    at android.view.LayoutInflater.createView(LayoutInflater.java:505)
    ... 23 more
Caused by: java.lang.OutOfMemoryError: bitmap size exceeds VM budget
    at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method)
    at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:460)
    at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:336)
    at android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:697)
    at android.content.res.Resources.loadDrawable(Resources.java:1709)
    at android.content.res.TypedArray.getDrawable(TypedArray.java:601)
    at android.widget.ImageView.<init>(ImageView.java:118)
    at android.widget.ImageView.<init>(ImageView.java:108)

这是我的 XML 代码:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">

<RelativeLayout
    android:id="@+id/RL_Title"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_weight="8"
    android:onClick="onTitleClick" >

    <ImageView
        android:id="@+id/Img_Title_bg"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scaleType="center"
        android:src="@drawable/title_bg" />

    <Button
        android:id="@+id/Btn_Title"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_centerVertical="true"
        android:layout_marginRight="5dp"
        android:background="@drawable/title_al"
        android:drawableRight="@drawable/pro"
        android:gravity="center"
        android:onClick="onTitleClick" />
</RelativeLayout>

<RelativeLayout
    android:id="@+id/RL_MainMenu"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_weight="1" android:onClick="onDoNothing">

    <ImageView
        android:id="@+id/ImageView01"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_weight="4"
        android:src="@drawable/main_bg" android:scaleType="centerCrop"/>

    <ImageView
        android:id="@+id/Img_logo"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_weight="4"
        android:scaleType="center"
        android:src="@drawable/logo_al" />

    <LinearLayout
        android:id="@+id/LI_Menu"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_above="@+id/RL_ExtraOption"
        android:layout_alignTop="@+id/Img_logo"
        android:layout_margin="2dp"
        android:orientation="vertical" >

        <ImageButton
            android:id="@+id/Img_Buyer"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_margin="1dp"
            android:layout_weight="1"
            android:background="@drawable/bt_blink"
            android:onClick="Nextclick"
            android:scaleType="fitCenter"
            android:soundEffectsEnabled="true"
            android:src="@drawable/buyer_icon" />

        <ImageButton
            android:id="@+id/Img_Seller"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_margin="1dp"
            android:layout_weight="1"
            android:background="@drawable/bt_blink"
            android:onClick="Nextclick"
            android:scaleType="fitCenter"
            android:src="@drawable/seller_icon" />

        <ImageButton
            android:id="@+id/Img_Lender"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_margin="1dp"
            android:layout_weight="1"
            android:background="@drawable/bt_blink"
            android:onClick="Nextclick"
            android:scaleType="fitCenter"
            android:src="@drawable/lender_icon" />

        <ImageButton
            android:id="@+id/Img_myTitleRep"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_margin="1dp"
            android:layout_weight="1"
            android:background="@drawable/bt_blink"
            android:onClick="Nextclick"
            android:scaleType="fitCenter"
            android:src="@drawable/my_title_rep_icon_al" />

        <ImageButton
            android:id="@+id/Img_Setup"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_margin="1dp"
            android:layout_weight="1"
            android:background="@drawable/bt_blink"
            android:onClick="Nextclick"
            android:scaleType="fitCenter"
            android:src="@drawable/setup_icon" />
    </LinearLayout>

    <RelativeLayout
        android:id="@+id/RL_ExtraOption"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:background="@drawable/main_bottom_bg" >

        <TextView
            android:id="@+id/txt_RepName"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerVertical="true"
            android:layout_marginLeft="10dp"
            android:textColor="@color/white"
            android:textSize="@dimen/font_size" />

        <TableRow
            android:id="@+id/TR_ContactRep"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentRight="true"
            android:layout_centerVertical="true"
            android:gravity="center" >

            <Button
                android:id="@+id/Btn_ContactRep"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginRight="3dp"
                android:background="@drawable/contact_rep_blink"
                android:onClick="ContactRep_Click" />

            <Button
                android:id="@+id/Btn_MoreOption"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginRight="5dp"
                android:background="@drawable/main_more_blink"
                android:onClick="onMoreClick" />
        </TableRow>
    </RelativeLayout>

    <LinearLayout
        android:id="@+id/ln_Mainmore"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@drawable/dialog_bg" android:layout_alignParentBottom="true" android:visibility="gone">

        <LinearLayout
            android:id="@+id/LinearLayout02"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_weight="3"
            android:orientation="vertical" >
        </LinearLayout>

        <TableLayout
            android:id="@+id/TableLayout01"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:gravity="center" >

            <TableRow
                android:id="@+id/TableRow04"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:layout_margin="5dp"
                android:layout_marginTop="20dp"
                android:gravity="center" >

                <Button
                    android:id="@+id/Btn_Rate"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:layout_weight="1"
                    android:background="@drawable/property_blue_blink"
                    android:onClick="onRate"
                    android:singleLine="true"
                    android:text="Rate/Testimonial"
                    android:textColor="@color/white"
                    android:textSize="@dimen/font_size"
                    android:textStyle="bold" />
            </TableRow>

            <TableRow
                android:id="@+id/TableRow01"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:layout_margin="5dp"
                android:gravity="center" >

                <Button
                    android:id="@+id/btn_SubFeature"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:layout_weight="1"
                    android:background="@drawable/property_blue_blink"
                    android:onClick="onSubFeature"
                    android:singleLine="true"
                    android:text="Submit A Feature"
                    android:textColor="@color/white"
                    android:textSize="@dimen/font_size"
                    android:textStyle="bold" />
            </TableRow>

            <TableRow
                android:id="@+id/TableRow03"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:layout_margin="5dp"
                android:gravity="center" >

                <Button
                    android:id="@+id/Btn_ReferFrnd"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:layout_weight="1"
                    android:background="@drawable/property_blue_blink"
                    android:onClick="onReferAFrnd"
                    android:text="Refer A Friend"
                    android:textColor="@color/white"
                    android:textSize="@dimen/font_size"
                    android:textStyle="bold" />
            </TableRow>

            <TableRow
                android:id="@+id/TableRow02"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:layout_margin="5dp"
                android:gravity="center" >

                <Button
                    android:id="@+id/Btn_cancel"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:layout_weight="1"
                    android:background="@drawable/property_cancel_blink"
                    android:onClick="onClose"
                    android:text="Cancel"
                    android:textColor="@color/black"
                    android:textSize="@dimen/font_size"
                    android:textStyle="bold" />
            </TableRow>
        </TableLayout>

        <LinearLayout
            android:id="@+id/linearLayout2"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_weight="3"
            android:orientation="vertical" >
        </LinearLayout>
    </LinearLayout>

</RelativeLayout>

4

8 回答 8

62

我想问题不在于您的布局;问题出在代码中的其他地方。而且您可能正在某处泄漏上下文

其他可能的原因是您在解析 XML 时必须创建大量的多个对象(正如您提到的,这在您解析 XML 时第一次发生)。虽然 Java 有自动垃圾回收的方法,但你仍然不能完全依赖它。当您不再需要它们时,取消您的集合实例或清除您的对象内容是一种很好的做法。

但是我仍然准备了一个重要的点列表,在 Android 上处理位图时应该记住这些点。

1)您可以在每个位图上调用回收并将它们设置为空。(bitmap.recycle()将释放此位图使用的所有内存,但不会使位图对象无效)。

2)您也可以drawables在活动被销毁时解除与布局关联的绑定。试试下面给出的代码,也看看这个链接链接

    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();
        }
    }

// Call this method from onDestroy()

    void onDestroy() {
        super.onDestroy();
        unbindDrawables(findViewById(R.id.RootView));
        System.gc();
    }

3)您可以将您的转换hashmapsWeakHashmaps,以便在系统内存不足时释放其内存。

4)您可以缩放/调整所有位图的大小。要缩放位图,您可以尝试以下操作:

    BitmapFactory.Options options = new BitmapFactory.Options();
    options.inSampleSize = 8;
    Bitmap preview_bitmap=BitmapFactory.decodeStream(is, null, options);

这个 inSampleSize 选项减少了内存消耗。

这是一个完整的方法。首先它读取图像大小而不解码内容本身。然后它找到最好的 inSampleSize 值;它应该是 2 的幂。最后,图像被解码。

// Decodes image and scales it to reduce memory consumption
private Bitmap decodeFile(File f){
    try {
        // Decode image size
        BitmapFactory.Options o = new BitmapFactory.Options();
        o.inJustDecodeBounds = true;
        BitmapFactory.decodeStream(new FileInputStream(f),null,o);

        // The new size we want to scale to
        final int REQUIRED_SIZE=70;

        // Find the correct scale value. It should be the power of 2.
        int scale=1;
        while(o.outWidth/scale/2 >= REQUIRED_SIZE && o.outHeight/scale/2 >= REQUIRED_SIZE)
            scale*=2;

        // Decode with inSampleSize
        BitmapFactory.Options o2 = new BitmapFactory.Options();
        o2.inSampleSize=scale;
        return BitmapFactory.decodeStream(new FileInputStream(f), null, o2);
    }
    catch (FileNotFoundException e) {
    }
    return null;
}

看看这个链接。.

5)您可以覆盖onLowMemory()活动中的方法,当整个系统内存不足时会调用该方法。你可以在那里释放一些资源。

6)您可以制作您的对象SoftReferenceor Weakreference,以便它们在内存不足的情况下被释放。

我观察到的一个非常常见的内存泄漏是由于内部类的实现和HandlerActivity. 此链接更详细地讨论了相同的内容

我希望这有助于消除您的问题。

于 2012-05-02T06:40:16.690 回答
6

这是在旧设备上使用带有大图像的 Android 时的典型问题ImageView(即使文件大小只有几个 Kbs)。用于解码图像的名为skia的本机图形库根据图像的尺寸分配本机内存,因此文件大小不会直接影响这一点。

即使您src在 XML 布局定义中省略 - 属性以在您的onCreate()方法中自己加载图像,也会触发相同的错误。解决此问题的唯一方法是在解码期间使用inSampleSizeinBitmapFactory.decodeStream直接执行下采样(例如,请参阅将图像加载到 Bitmap 对象时出现奇怪的内存不足问题)。这本身就提出了如何确定这个比例因子的问题。

我在处理大图像时发现的最佳解决方案是用ImageViewa替换WebView并加载一些最小的 HTML,如下所示:

webView.loadUrl("file:///android_res/raw/background.html");

其中的内容raw/background.html可能是这样的:

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
    <style type="text/css">
        body {
            margin: 0;
        }

        img {
            width: 100%;
            height: auto;
            display: block;
        }
    </style>
</head>
<body>
    <img src="file:///android_res/drawable/background.png" />
</body>

WebView 中使用的 WebKit 引擎以更有效的方式执行图像加载,因此那些内存分配错误应该消失。

您甚至可以将不同的图像用于纵向和横向,只需将它们放入drawable-portdrawable-land. 但是您必须clearCache(false)在您的方法中调用 WebView 实例,onDestroy()否则将始终使用第一次加载时缓存的图像(禁用 WebView 实例上的缓存不起作用)。

于 2012-05-06T14:15:24.950 回答
6

在这个问题上花了很多时间后,我找到了解决方案!您需要做的就是要求更多的内存。将此代码放在您的android清单中:

<application>:

放:

android:largeHeap="true"

对我来说很棒!请注意,此解决方案仅适用于 API 11 及更高版本。

更多信息在这里。

于 2015-11-16T11:00:14.830 回答
4

许多设备的每个设备可用的内存非常有限。许多旧设备为您的应用程序分配 16MB 内存,而一些更现代的设备可能会分配 24MB 甚至 32MB(我见过只有 14MB 的设备)。

每当您将如此多的图像加载到内存中时,这个空间很快就会被填满,从而导致 OutOfMemoryError 被抛出。为了克服这个问题,您应该(如先前的答案所说)将图像缩小为缩略图,只将缩略图保留在设备内存中(减少内存占用)并将图像保存到 SDCARD。

您可以从 Eclipse 的 DDMS 布局中查看您的程序使用了多少内存。我相信您还可以覆盖 Application 类来监听“内存不足”警告功能。

当您通过 BitmapFactory 读取位图时,将 BitmapFactory.Option inScaled 参数设置为 2 或 4(或任何适合您的值)以创建更小、内存占用更少的图像。

通常,只有一种解决方案:使用较小的图像。如果没有代码,很难说到底出了什么问题。您可以尝试降低图像尺寸。

于 2012-04-30T10:47:32.113 回答
4

除了人们在这里写的内容之外,我建议观看 google 的这个视频,它指出了一些常见的内存问题以及如何找到内存问题的原因:

Android 应用程序的内存管理

于 2012-05-05T18:05:23.710 回答
3

我之前遇到过同样的问题,我在 S4 android 4.3 上进行调试。解决方案是:将图像从 mdpi 文件夹复制到 hdpi 文件夹(因此它们现在位于两个文件夹中)

我知道奇怪!但这解决了我的问题。

于 2014-04-19T16:59:12.127 回答
3

它看起来像你的图像很大,所以你可以解码你的图像并使用 android:largeHeap="true"。应用程序标签的清单内部

于 2015-12-23T09:17:11.097 回答
0

您可能已经完成了上述所有解决方案,但仍然试一试。在找到解决方案之前,我一直在寻找解决方案。这可能适用于您的情况(在这种情况下请原谅)。

myIntent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY | Intent.FLAG_ACTIVITY_CLEAR_TASK); myIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);

在你调用你的活动之前放置这些。

于 2013-09-05T00:11:58.057 回答