IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Android Discussion :

GridView et Out of memory


Sujet :

Android

  1. #1
    Membre éprouvé

    Inscrit en
    Décembre 2009
    Messages
    146
    Détails du profil
    Informations forums :
    Inscription : Décembre 2009
    Messages : 146
    Points : 900
    Points
    900
    Par défaut GridView et Out of memory
    Bonjour,

    Depuis que j'essaye mon application sur android 2.3.3, elle ne fonctionne plus.

    Mon activity possède 2 GridView avec quelques icônes. Et des que je passe d'un "contentview" à un autre 1 fois de trop, j'ai un message d'erreur qui m'a l'air de poser des problèmes à beaucoup de gens au vu de mes recherches :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    06-14 01:12:44.414: ERROR/AndroidRuntime(7432): FATAL EXCEPTION: main
    06-14 01:12:44.414: ERROR/AndroidRuntime(7432): java.lang.OutOfMemoryError: bitmap size exceeds VM budget
    06-14 01:12:44.414: ERROR/AndroidRuntime(7432):     at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method)
    06-14 01:12:44.414: ERROR/AndroidRuntime(7432):     at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:460)
    06-14 01:12:44.414: ERROR/AndroidRuntime(7432):     at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:336)
    06-14 01:12:44.414: ERROR/AndroidRuntime(7432):     at android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:697)
    06-14 01:12:44.414: ERROR/AndroidRuntime(7432):     at android.content.res.Resources.loadDrawable(Resources.java:1782)
    06-14 01:12:44.414: ERROR/AndroidRuntime(7432):     at android.content.res.Resources.getDrawable(Resources.java:588)
    06-14 01:12:44.414: ERROR/AndroidRuntime(7432):     at android.widget.ImageView.resolveUri(ImageView.java:501)
    06-14 01:12:44.414: ERROR/AndroidRuntime(7432):     at android.widget.ImageView.setImageResource(ImageView.java:280)
    Donc d'après ma recherche, j'utilise trop de mémoire (O_o), je veux bien, mais j'ai juste un Xml qui défini le GridView et ci-dessous le code de mon adapter :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    public class MenuGridViewAdapter extends BaseAdapter
    {
    	private ArrayList<Integer> idIconList;
    	private Context context;
    	private int screenWidth;
     
    	public MenuGridViewAdapter(Context c, ArrayList<Integer> list)
    	{
    		context = c;
    		idIconList = list;
    		Display display = ((WindowManager) context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay(); 
    		screenWidth = display.getWidth();
    	}
     
    	public int getCount()
    	{
    		return idIconList.size();
    	}
     
    	public Object getItem(int item)
    	{
    		return item;
    	}
     
    	public long getItemId(int arg0)
    	{
    		return 0;
    	}
     
    	public View getView(int position, View convertView, ViewGroup parent)
    	{
    		ImageView imageView;
    		// Calcul de la dimension maximum des marges
    		int margin = (int) (screenWidth * 3 / 100);
    		// Calcul de la dimension maximum des icônes
    		int size = (int)((screenWidth - 4 * margin) / 3);
    		if (convertView == null)
    		{
    			imageView = new ImageView(context);
    			imageView.setPadding(margin, margin, margin, margin);
    			imageView.setScaleType(ImageView.ScaleType.FIT_START);
    			imageView.setLayoutParams(new GridView.LayoutParams(size, size));
    			imageView.setImageResource(idIconList.get(position));
    		}
    		else
    			imageView = (ImageView) convertView;
    		return imageView;
    	}
    }
    J'avais pour idée de désallouer par un recycle tous les éléments (imageview) du GridView mais je ne vois pas très bien comment faire ?

    Et puis ça me parait étrange que cela ne soit pas fait automatiquement par le système non ?

    Merci d'avance.

  2. #2
    Expert éminent

    Avatar de Feanorin
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    4 589
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 4 589
    Points : 9 149
    Points
    9 149
    Par défaut
    Bonjour,

    Et puis ça me parait étrange que cela ne soit pas fait automatiquement par le système non ?
    Le garbage collector ne fait pas tout .
    il faut libérer la mémoire prise d'une image car il le garde dans le cache.

    Pour cela tu peux faire une recherche sur le forum , il y a pas mal de sujet ouvert la dessus .

    De mémoire il faut effectuer un recycle avant un changement d'image.
    Responsable Android de Developpez.com (Twitter et Facebook)
    Besoin d"un article/tutoriel/cours sur Android, consulter la page cours
    N'hésitez pas à consulter la FAQ Android et à poser vos questions sur les forums d'entraide mobile d'Android.

  3. #3
    Membre éprouvé

    Inscrit en
    Décembre 2009
    Messages
    146
    Détails du profil
    Informations forums :
    Inscription : Décembre 2009
    Messages : 146
    Points : 900
    Points
    900
    Par défaut
    Donc si j'ai un Xml de ce genre :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    <?xml version="1.0" encoding="utf-8"?>
    <ScrollView
      xmlns:android="http://schemas.android.com/apk/res/android"
      android:layout_width="fill_parent"
      android:layout_height="fill_parent"
      android:background="@drawable/bg"
      android:id="@+id/globalScrollView">
    <LinearLayout
      android:layout_width="fill_parent"
      android:layout_height="fill_parent"
      android:orientation="vertical">
    	<ImageButton
    	 	android:layout_width="48dip"
    	 	android:layout_height="48dip"
    	 	android:background="@drawable/arrow_left"
    	 	android:layout_marginLeft="5dip"
    	 	android:id="@+id/leftArrow">
    	</ImageButton>
      	<ImageButton
      		android:layout_width="48dip"
      		android:layout_height="48dip"
      		android:background="@drawable/arrow_right"
      		android:layout_gravity="right"
      		android:layout_marginRight="5dip"
      		android:id="@+id/rightArrow">
      	</ImageButton>
      </LinearLayout>
      <ImageView
      	android:id="@+id/instructions"
      	android:layout_marginTop="20dip"
    	android:adjustViewBounds="true"
      	android:layout_height="wrap_content"
      	android:layout_width="fill_parent">
      </ImageView>
    </LinearLayout>
    </ScrollView>
    Quand je change passe à un autre layout il faut que je désalloue les 3 imageViews ? O_o J'ai jamais eu à le faire avant mais pourquoi pas (sur d'autres applications).

    Et sur le GridView je veux bien le faire, mais comment accéder au Bitmap de chaque élement ?
    Je vais quand même essayer des choses dans ce sens pour voir

  4. #4
    Expert éminent

    Avatar de Feanorin
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    4 589
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 4 589
    Points : 9 149
    Points
    9 149
    Par défaut
    Quand je change passe à un autre layout il faut que je désalloue les 3 imageViews ? O_o J'ai jamais eu à le faire avant mais pourquoi pas (sur d'autres applications).
    Je me recite , le problème est qu'il garde en cache , donc lorsque tu changes ton l'image de ton imageview, la mémoire prise par ton image n'est pas désalloué. Maintenant peut être cela est le cas pour le ContentView.
    Je ne te demande pas de désalloué à chaque imageview , mais juste quand tu changes le cache de tes imageView.

    Et sur le GridView je veux bien le faire, mais comment accéder au Bitmap de chaque élement ?
    Je vais quand même essayer des choses dans ce sens pour voir
    Après pour les gridview normalement elle s'occupe toute seule de la mémoire. Mais si tu changes de contentView durant ton activity peut être cela lui pose problème .


    NB: Juste une petite précision on peut changer de ContentView durant une activity , mais je pense que cela doit poser problème à Android au niveau de la gestion de la mémoire entre le changement de ContentView.

    Si tu veux libérer ta bitmap de ton imageview . il faut alors récupérer le pointeur de cette imagview.
    Responsable Android de Developpez.com (Twitter et Facebook)
    Besoin d"un article/tutoriel/cours sur Android, consulter la page cours
    N'hésitez pas à consulter la FAQ Android et à poser vos questions sur les forums d'entraide mobile d'Android.

  5. #5
    Membre éclairé
    Avatar de ZouBi
    Inscrit en
    Octobre 2007
    Messages
    508
    Détails du profil
    Informations professionnelles :
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Octobre 2007
    Messages : 508
    Points : 812
    Points
    812
    Par défaut
    Peux tu nous dire quel est le format de tes images, et leur poids?

  6. #6
    Membre éprouvé

    Inscrit en
    Décembre 2009
    Messages
    146
    Détails du profil
    Informations forums :
    Inscription : Décembre 2009
    Messages : 146
    Points : 900
    Points
    900
    Par défaut
    Citation Envoyé par Feanorin Voir le message
    Je me recite , le problème est qu'il garde en cache , donc lorsque tu changes ton l'image de ton imageview, la mémoire prise par ton image n'est pas désalloué. Maintenant peut être cela est le cas pour le ContentView.
    Je ne te demande pas de désalloué à chaque imageview , mais juste quand tu changes le cache de tes imageView.
    oui justement je change carrément de ContentView, je ne modifie pas le contenu des imageview.


    Citation Envoyé par Feanorin Voir le message
    Après pour les gridview normalement elle s'occupe toute seule de la mémoire. Mais si tu changes de contentView durant ton activity peut être cela lui pose problème .


    NB: Juste une petite précision on peut changer de ContentView durant une activity , mais je pense que cela doit poser problème à Android au niveau de la gestion de la mémoire entre le changement de ContentView.

    Si tu veux libérer ta bitmap de ton imageview . il faut alors récupérer le pointeur de cette imagview.
    Je vais voir pour récuperer ces infos



    Citation Envoyé par ZouBi Voir le message
    Peux tu nous dire quel est le format de tes images, et leur poids?
    png, 256*256 pour la plupart, et du 512x512 pour quelques unes.

  7. #7
    Membre éclairé
    Avatar de ZouBi
    Inscrit en
    Octobre 2007
    Messages
    508
    Détails du profil
    Informations professionnelles :
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Octobre 2007
    Messages : 508
    Points : 812
    Points
    812
    Par défaut
    Tes images me paraient grosses et lourdes;
    C'est pour ça que dans les gridview, on utilise des miniatures pour éviter ce genre de problèmes. De toute façon, une gridview n'affichera jamais une image à 512*512, elle le redimensionnera toujours.

  8. #8
    Membre éprouvé

    Inscrit en
    Décembre 2009
    Messages
    146
    Détails du profil
    Informations forums :
    Inscription : Décembre 2009
    Messages : 146
    Points : 900
    Points
    900
    Par défaut
    Mais alors comment faire sur des tablettes qui proposent des résolutions très grandes ?
    Et le problème reviendra lorsque ma gridview contiendra des centaines d'éléments :'(

  9. #9
    Expert éminent

    Avatar de Feanorin
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    4 589
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 4 589
    Points : 9 149
    Points
    9 149
    Par défaut
    Mais alors comment faire sur des tablettes qui proposent des résolutions très grandes ?
    Et le problème reviendra lorsque ma gridview contiendra des centaines d'éléments :'(
    La gridView ne charge en mémoire que les images présente à l'écran , je me répète mais il y a un sujet parlant de cette gestion dans le forum.

    Par exemple :
    http://www.developpez.net/forums/d10...ment-listview/

    Il y a d'autre sujet sur le forum

    png, 256*256 pour la plupart, et du 512x512 pour quelques unes.
    Tu peux réduire ces images si tu le souhaites mais cela passe .


    Edit : peut être cela vient du fait du changement de Layout dans ton activity il faudrait que tu log la mémoire alloué pour voir comment elle interagie lors du changement de vue .
    Responsable Android de Developpez.com (Twitter et Facebook)
    Besoin d"un article/tutoriel/cours sur Android, consulter la page cours
    N'hésitez pas à consulter la FAQ Android et à poser vos questions sur les forums d'entraide mobile d'Android.

  10. #10
    Membre éclairé
    Avatar de ZouBi
    Inscrit en
    Octobre 2007
    Messages
    508
    Détails du profil
    Informations professionnelles :
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Octobre 2007
    Messages : 508
    Points : 812
    Points
    812
    Par défaut
    Citation Envoyé par Sylvaner Voir le message
    Mais alors comment faire sur des tablettes qui proposent des résolutions très grandes ?
    Et le problème reviendra lorsque ma gridview contiendra des centaines d'éléments :'(
    Surement que les tablettes proposent une mémoire pour ton application plus grande ne causant pas un dépassement de mémoire. A tester.
    C'est pour ça aussi qu'on utilise les dossiers drawables différents pour chaque résolution.

  11. #11
    Membre éprouvé

    Inscrit en
    Décembre 2009
    Messages
    146
    Détails du profil
    Informations forums :
    Inscription : Décembre 2009
    Messages : 146
    Points : 900
    Points
    900
    Par défaut
    J'ai résolu le problème en partie en chargeant un bitmap redimensionné, mais là j'ai un problème de lenteur du coup, le contentview met plus de temps à se charger.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    Bitmap temp = BitmapFactory.decodeResource(context.getResources(), idIconList.get(position));
    			bitmapBuffer.add(Bitmap.createScaledBitmap(temp, size, size, true));
    			temp.recycle();
    			temp = null;
    			imageView.setImageBitmap(bitmapBuffer.get(bitmapBuffer.size() - 1));
    PS : j'ai ajouté une méthode recycle à mon adapter pour vider le "bitmapBuffer"


    Edit : Encore mieux, je "précharge" tous mes bitmap et je les balances dans l'adapter directement. Ca met un poil de temps à charger au début, mais après c'est super réactif.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [XStream][String]out of memory
    Par Invité dans le forum Persistance des données
    Réponses: 8
    Dernier message: 10/01/2006, 14h52
  2. [C++] [gcc] out of memory
    Par fxp17 dans le forum GCC
    Réponses: 5
    Dernier message: 06/01/2006, 10h29
  3. [pb mémoire] out of memory d'eclipse
    Par Casp dans le forum Eclipse Java
    Réponses: 2
    Dernier message: 12/05/2005, 16h39
  4. Out of memory
    Par shurato dans le forum ANT
    Réponses: 1
    Dernier message: 10/11/2004, 16h19
  5. [JBuilder 8] Out of memory problem ...
    Par keros dans le forum JBuilder
    Réponses: 2
    Dernier message: 08/09/2003, 19h03

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo