Affichage d'images jpg : java.lang.OutOfMemoryError

[Résolu/Fermé]
Signaler
Messages postés
7
Date d'inscription
samedi 23 août 2014
Statut
Membre
Dernière intervention
17 mars 2015
-
Messages postés
7
Date d'inscription
samedi 23 août 2014
Statut
Membre
Dernière intervention
17 mars 2015
-
Bonjour !

Je suis en train de créer une application android qui affiche une image par page (par activité). En cliquant sur un bouton, on passe à une nouvelle page (nouvelle activité) et on affiche une nouvelle image.

Cependant, je rencontre de temps un problème : de temps en temps l'application se ferme et le débogueur affiche :

03-16 11:57:05.881 15713-15713/fr.maxiapp.lesaliments E/AndroidRuntime? FATAL EXCEPTION: main
Process: fr.maxiapp.lesaliments, PID: 15713
java.lang.OutOfMemoryError
at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method)
at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:594)
at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:429)
at android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:856)
at android.content.res.Resources.loadDrawable(Resources.java:2122)
at android.content.res.Resources.getDrawable(Resources.java:707)
at android.widget.ImageView.resolveUri(ImageView.java:638)
at android.widget.ImageView.setImageResource(ImageView.java:367)
at fr.maxiapp.lesaliments.AffichageIdeeActivity.onCreate(AffichageIdeeActivity.java:95)
at android.app.Activity.performCreate(Activity.java:5240)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1088)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2216)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2301)
at android.app.ActivityThread.access$800(ActivityThread.java:144)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1246)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:5196)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:602)
at dalvik.system.NativeStart.main(Native Method)


L'affichage d'une image se fait de la façon suivante :

image_en_cours.setImageResource(img.getUneImage(numImageEnCours+1));

Avec img.getUneImage(numImageEnCours+1) renvoyant un identifiant (int) de la forme R.drawable.imageXXX.

Naturellement, j'ai cherché cette erreur sur google, et elle indique apparemment un problème de mémoire (photo trop lourde ?) mais je ne trouve pas de solution pour la corriger.
Peut-être que je libère mal la mémoire après en avoir fini avec une image ?

Auriez-vous une solution ?

Je vous remercie d'avance :)

A bientôt !

5 réponses

Messages postés
7
Date d'inscription
samedi 23 août 2014
Statut
Membre
Dernière intervention
17 mars 2015

Bonjour et merci pour ta réponse.

En réalité, je ne libère pas vraiment la mémoire quand j'y pense : j'avais essayé de mettre tout un tas de trucs différents dans la méthode onDestroy() mais rien ne corrigeait le problème.

La libération de la mémoire est bien censée être ordonnée dans cette méthode ?
Et quelle commande appeler ?
J'avais essayé ça :


unbindDrawables(findViewById(R.id.mainLayout));
System.gc();


Mais sans succès ...

Merci de votre aide !
Messages postés
7
Date d'inscription
samedi 23 août 2014
Statut
Membre
Dernière intervention
17 mars 2015

Je parle de la méthode onDestroy, commune à chaque activité Android.

J'entends bien que chaque situation est différente mais je ne vois pas quel autre bout de code t'intéresserait. Le reste ne concerne ni l'affichage d'une image ni la libération de la mémoire associée.

En réalité, ma question est très précise : comment afficher une image jpg tout en évitant cette erreur ? Qu'écrire dans la méthode onDestroy() pour libérer la mémoire d'une image ?

Si tu y tiens , je peux vous transmettre tout le code de mon activité mais je doute que cela te soit très utile ...

Merci en tout cas :)
Messages postés
15136
Date d'inscription
lundi 11 juillet 2005
Statut
Modérateur
Dernière intervention
20 septembre 2021
3 638
Hello,

Effectivement, c'est un souci de mémoire. Plusieurs solutions:
- retailler tes images: inutile d'avoir des images de 2500x2500 pixels sur un téléphone
- redimensionner à la volée ton image en fonction de ta taille d'écran avec, de mémoire, la méthode
Bitmap.createScaledBitmap()

Messages postés
7
Date d'inscription
samedi 23 août 2014
Statut
Membre
Dernière intervention
17 mars 2015

Salut :)
J'ai essayé de suivre ton conseil et ça ne marche pas beaucoup mieux ...
En revanche, j'ai suivi le Memory Monitor sur Android Studio et me suis rendu compte qu'à chaque nouvelle activité, 5 ou 6 mo étaient alloués en plus (or une image fait 40ko).
Et à partir d'un peu moins de 100 mo, l'application plante.

Mais le problème vient en réalité de la publicité admob que j'ai insérée. Aucun problème quand je désactive la pub.
Pour résoudre mon problème, je supprime manuellement à la fin de chaque activité l'objet AdView avec la méthode adView.destroy();

Et ça a l'air d'un peu mieux marcher. Mais je trouve tout de même bizarre que la Garbage Collector ne supprime pas les objets AdView à la fin d'une activité.

Voici le code correspondant à l'affichage de la pub :


adView = new AdView(this);
adView.setAdUnitId("ca-app-pub-******");
adView.setAdSize(AdSize.SMART_BANNER);
// Recherchez l'entité LinearLayout en supposant qu'elle est associée à
// l'attribut android:id="@+id/mainLayout".
RelativeLayout layout = (RelativeLayout)findViewById(R.id.pub);
// Ajoutez-y l'objet adView.
layout.addView(adView);
// Initiez une demande générique.
AdRequest adRequest = new AdRequest.Builder().build();
// Chargez l'objet adView avec la demande d'annonce.
adView.loadAd(adRequest);



Bref, tout cela est bien bizarre mais plus ou moins résolu.
Messages postés
15136
Date d'inscription
lundi 11 juillet 2005
Statut
Modérateur
Dernière intervention
20 septembre 2021
3 638
Le GC n'est pas un outil magique: quand il fait son petit tour, il regarde ce qu'il peut récupérer = les objets qui n'ont plus de référence. Ici, ta pub était toujours attachée, donc il est normal de faire un destroy dessus:
https://developer.android.com/reference
Messages postés
7
Date d'inscription
samedi 23 août 2014
Statut
Membre
Dernière intervention
17 mars 2015

Effectivement, j'avais omis de faire ça.
Merci beaucoup pour votre aide :)
A bientôt !