Причина: java.lang.OutOfMemoryError: размер растрового изображения превышает бюджет виртуальной машины

В моем приложении, когда я пытаюсь запустить его, Force Closed и ошибка указывает на строку "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>

8 ответов

Решение

Я думаю, что проблема не в вашем макете; проблема где-то еще в вашем коде. И вы, вероятно, пропускаете контекст где-то.

Другая вероятная причина заключается в том, что при синтаксическом анализе XML вы должны создавать громоздкие несколько объектов (как вы упоминали, это происходит в первый раз, когда вы анализируете XML). Хотя в Java есть метод автоматического сбора мусора, но все же вы не можете полностью полагаться на него. Хорошей практикой является аннулирование экземпляра вашей коллекции или очистка содержимого ваших объектов, когда они вам больше не нужны.

Но все же я подготовил список важных моментов, которые вы должны помнить при работе с растровыми изображениями на Android.

1) Вы можете вызвать recycle для каждого растрового изображения и установить для него значение null. (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) Вы можете конвертировать ваши hashmaps в WeakHashmaps, так что его память будет освобождена, когда системе не хватает памяти.

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) Вы можете сделать свои объекты SoftReference или же Weakreference, так что они освобождаются в состоянии нехватки памяти.

Наблюдаемая мною очень частая утечка памяти связана с реализацией внутренних классов и реализацией Handler в Activity, Эта ссылка говорит о том же более подробно.

Я надеюсь, что это поможет устранить вашу проблему.

Потратив много времени на эту проблему, я нашел решение! Все, что вам нужно сделать, это попросить больше памяти. Поместите этот код в свой манифест Android под:

<application>:

Положил:

android:largeHeap="true"

Отлично сработало для меня! Обратите внимание, что это решение работает только на API 11 и выше.

Больше информации здесь.

Это типичная проблема при использовании Android ImageView с большими изображениями на старых устройствах (даже если размер файла составляет всего несколько килобайт). Собственная графическая библиотека, называемая skia, которая используется для декодирования изображения, выделяет собственную память на основе размеров изображения, поэтому размер файла не влияет на это напрямую.

Даже если вы опустите srcатрибут в определении макета XML, чтобы загрузить изображение самостоятельно в ваш onCreate() Метод та же ошибка будет вызвана. Единственный способ обойти это, это использовать inSampleSize в BitmapFactory.decodeStream выполнить понижающую дискретизацию непосредственно во время декодирования (см., например, Странная проблема с нехваткой памяти при загрузке изображения в объект Bitmap, например). Это само по себе поднимает вопрос о том, как определить этот масштабный коэффициент.

Лучшее решение, которое я нашел при обработке больших изображений, это замена ImageView с 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>

Механизм WebKit, который используется в WebView, выполняет загрузку изображений гораздо более эффективным способом, поэтому эти ошибки распределения памяти должны быть устранены.

Вы даже можете использовать разные изображения для портрета и пейзажа, помещая их в drawable-port а также drawable-land, Но тогда вы должны позвонить clearCache(false) на экземпляре WebView в вашем onDestroy() метод, потому что в противном случае всегда будет использоваться изображение, кэшированное при первой загрузке (отключение кэширования в экземпляре WebView не работает).

В дополнение к тому, что люди написали здесь, я предлагаю посмотреть это видео о Google, которое указывает на некоторые распространенные проблемы с памятью и как найти причину вашей проблемы с памятью:

Управление памятью для приложений Android

Многие устройства имеют очень ограниченную и ограниченную память, доступную для каждого устройства. Многие старые устройства выделяют 16 МБ памяти для вашего приложения, в то время как некоторые более современные устройства могут выделять 24 МБ или даже 32 МБ (я видел устройство только с 14 МБ).

Всякий раз, когда вы загружаете столько памяти в память, это пространство очень быстро заполняется, вызывая выброс OutOfMemoryError. Чтобы преодолеть эту проблему, вы должны (как уже было сказано в предыдущих ответах) сжимать изображения до миниатюр и сохранять только миниатюры в памяти устройства (уменьшенный объем памяти) и сохранять изображения на SDCARD.

Вы можете увидеть, сколько памяти использует ваша программа, из макета DDMS в Eclipse. Я полагаю, что вы также можете переопределить класс Application для прослушивания функции предупреждения "Недостаточно памяти".

Когда вы читаете в Bitmap через BitmapFactory, установите для параметра BitmapFactory.Option inScaled значение 2 или 4 (или все, что вам подходит), чтобы создать меньшее, менее интенсивное использование памяти.

Как правило, есть только одно решение: использовать меньшие изображения. Если нет кода, трудно сказать, что именно не так. Вы можете попытаться уменьшить размер изображения.

Он выглядит так, как будто ваше изображение большого размера, так что вы можете декодировать свое изображение и использовать Android:largeHeap="true". внутри манифеста тега приложения

У меня была такая же проблема раньше, и я отлаживал на S4 android 4.3. Решение было: скопируйте изображения из папки mdpi в папку hdpi (чтобы они теперь были в обеих папках)

Я знаю странно! но это решило мою проблему.

Вы могли бы пройти через все вышеупомянутые решения, но все же попробовать. Я был потерян в поиске решения, пока не получил его работу. Это может сработать ночью для вашего случая (извините в этом случае).

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

разместите их, прежде чем называть свою деятельность.

Другие вопросы по тегам