web-dev-qa-db-fra.com

Causé par: Java.lang.OutOfMemoryError: la taille du bitmap dépasse VM budget

Dans mon application lorsque j'essaye de le lancer, Forcer la fermeture et l'erreur pointant la ligne "setContentView (R.layout.Menu);" de la mise en page. Et dans le fichier XML, il montre la vue d'image "OutOfMemoryError" dans ma mise en page. Je suis vraiment confus. Veuillez me guider pour un déménagement ultérieur.

Modifié:

Mon application utilise une base de données et, à la toute première fois, elle analyse des données XML et les insère dans la base de données Sqlite. Mon problème Outofmemory ne se produit que la première fois. La deuxième fois, cela fonctionne bien. J'ai essayé System.gc (). Y a-t-il un problème à ce sujet.

Ceci est mon journal:

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)

Voici mon code 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>
27
Sniper

Je suppose que le problème n'est pas dans votre mise en page; le problème est ailleurs dans votre code. Et vous avez probablement une fuite de contexte quelque part.

Une autre raison probable est que vous devez créer plusieurs objets volumineux lors de l'analyse de votre XML (comme vous l'avez mentionné, cela se produit la première fois lorsque vous analysez XML). Bien que Java a une approche de collecte automatique des ordures, mais vous ne pouvez toujours pas vous y fier complètement. C'est une bonne pratique de annuler votre instance de collection ou effacer le contenu de vos objets lorsque vous ne le faites pas ' je n'en ai plus besoin.

Mais j'ai quand même préparé une liste de points importants dont vous devez vous souvenir lorsque vous traitez avec des bitmaps sur Android.

1) Vous pouvez appeler recycle sur chaque bitmap et les mettre à null. (bitmap.recycle() libérera toute la mémoire utilisée par ce bitmap, mais il n'annule pas l'objet bitmap).

2) Vous pouvez également dissocier le drawables associé aux présentations lorsqu'une activité est détruite. Essayez le code ci-dessous et regardez également ce lien link .

    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) Vous pouvez convertir votre hashmaps en WeakHashmaps, afin que sa mémoire soit libérée lorsque le système manque de mémoire.

4) Vous pouvez mettre à l'échelle/redimensionner tous vos bitmaps. Pour mettre à l'échelle des bitmaps, vous pouvez essayer quelque chose comme ceci:

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

Cette option inSampleSize réduit la consommation de mémoire.

Voici une méthode complète. Il lit d'abord la taille de l'image sans décoder le contenu lui-même. Ensuite, il trouve la meilleure valeur inSampleSize; ça devrait être une puissance de 2. Et enfin l'image est décodée.

// 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;
}

Jetez un oeil à ce lien. .

5) Vous pouvez remplacer la méthode onLowMemory() dans une activité qui reçoit un appel lorsque le système entier manque de mémoire. Vous pouvez y libérer quelques ressources.

6) Vous pouvez créer vos objets SoftReference ou Weakreference, afin qu'ils soient libérés dans une condition de mémoire insuffisante.

Une fuite de mémoire très courante que j'ai observée est due à l'implémentation de classes internes et à l'implémentation de Handler dans Activity. Ce lien parle de la même chose plus en détail .

J'espère que cela aide à éliminer votre problème.

61
N-JOY

Il s'agit d'un problème typique lors de l'utilisation de ImageView d'Android avec de grandes images sur des appareils plus anciens (même si la taille du fichier n'est que de plusieurs Ko). La bibliothèque graphique native appelée skia qui est utilisée pour décoder l'image alloue la mémoire native en fonction des dimensions de l'image, de sorte que la taille du fichier n'influence pas cela directement.

Même si vous omettez l'attribut src- dans la définition de disposition XML pour charger vous-même l'image dans votre méthode onCreate(), la même erreur sera déclenchée. La seule façon de contourner ce problème est d'utiliser un inSampleSize dans BitmapFactory.decodeStream Pour effectuer un sous-échantillonnage directement pendant le décodage (voir Problème de mémoire insuffisante lors du chargement d'une image dans un objet Bitmap par exemple). Cela pose en soi la question de savoir comment déterminer ce facteur d'échelle.

La meilleure solution que j'ai trouvée lors de la manipulation d'images volumineuses est de remplacer le ImageView par un WebView et de charger un peu de code HTML comme ceci:

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

où le contenu de raw/background.html pourrait ressembler à ceci:

<!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>

Le moteur WebKit utilisé dans WebView effectue le chargement d'image d'une manière beaucoup plus efficace, de sorte que ces erreurs d'allocation de mémoire devraient disparaître.

Vous pouvez même utiliser différentes images pour le portrait et le paysage en les mettant dans drawable-port Et drawable-land. Mais vous devez ensuite appeler clearCache(false) sur l'instance WebView dans votre méthode onDestroy() car sinon l'image mise en cache lors du premier chargement sera toujours utilisée (la désactivation de la mise en cache sur l'instance WebView ne fonctionne pas ).

6
Andreas Klöber

Après avoir passé beaucoup de temps sur ce problème, j'ai trouvé la solution! Il vous suffit de demander plus de mémoire. Placez ce code dans votre manifeste Android manifeste sous:

<application>:

Mettre:

Android:largeHeap="true"

Fonctionne très bien pour moi! Veuillez noter que cette solution ne fonctionne que sur l'API 11 et les versions ultérieures.

Plus d'informations ici.

5
Mark Kazakov

en plus de ce que les gens ont écrit ici, je suggère de regarder cette vidéo de google, qui pointe vers certains problèmes de mémoire courants et comment trouver la cause de votre problème de mémoire:

Gestion de la mémoire pour Android Apps

4

De nombreux appareils ont une mémoire très limitée et restreinte disponible pour chaque appareil. De nombreux appareils plus anciens allouent 16 Mo de mémoire à votre application, tandis que certains appareils plus modernes peuvent allouer 24 Mo ou même 32 Mo (j'ai vu un appareil avec seulement 14 Mo).

Chaque fois que vous chargez autant d'images en mémoire, cet espace se remplit très rapidement, provoquant le déclenchement de OutOfMemoryError. Pour surmonter ce problème, vous devez (comme les réponses précédentes l'ont dit) réduire les images en vignettes et ne conserver que les vignettes dans la mémoire de l'appareil (encombrement mémoire réduit) et enregistrer les images sur SDCARD.

Vous pouvez voir la quantité de mémoire utilisée par votre programme à partir de la disposition DDMS dans Eclipse. Je crois que vous pouvez également remplacer la classe Application pour écouter une fonction d'avertissement "Mémoire faible".

Lorsque vous lisez le bitmap via BitmapFactory, définissez le paramètre BitmapFactory.Option inScaled sur 2 ou 4 (ou tout ce qui vous convient) pour créer une image plus petite et moins gourmande en mémoire.

Généralement, il n'y a qu'une seule solution: utiliser des images plus petites. S'il n'y a pas de code, il est difficile de dire ce qui ne va pas. Vous pouvez essayer de réduire la taille de l'image.

4
Krishnakant Dalal

J'ai eu le même problème avant et je déboguais sur S4 Android 4.3. La solution était: Copiez les images du dossier mdpi vers le dossier hdpi (elles sont donc maintenant sur les deux dossiers) )

Je sais bizarre! mais cela a résolu mon problème.

3
Hasan Shouman

Il semble que votre image soit de grande taille, donc vous pouvez décoder votre image et utiliser Android: largeHeap = "true". dans le manifeste du tag d'application

2
Prakash

vous avez peut-être passé par toutes les solutions ci-dessus, mais essayez toujours. J'étais perdue à trouver une solution jusqu'à ce que je la fasse fonctionner. Cela pourrait fonctionner de nuit pour votre cas (Excusez-moi dans ce cas).

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

placez-les avant d'appeler votre activité.

0
Narasimha