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 :

Problème de mémoire avec des Bitmap


Sujet :

Android

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre prolifique
    Avatar de Ryu2000
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2008
    Messages
    10 241
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Décembre 2008
    Messages : 10 241
    Par défaut Problème de mémoire avec des Bitmap
    Bonjour,
    Je réalise une application dans laquelle il y a une GridView, en WXGA il y a 36 vignettes qui s'affichent, dans chaque vignette il y a un bitmap.

    En fait les images sont stocké dans une base de données en Blob.
    L'application les télécharge et les stock dans la base de donnée SQLite en Blob.
    Ensuite l'application récupère un byte[] qui est transformé en Bitmap, comme ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    public Bitmap byteToBitmap(byte[] image){
         BitmapFactory.Options opt = new BitmapFactory.Options();
         opt.inSampleSize = 8;
         opt.inTempStorage = new byte[16 * 1024];
         Bitmap bm = BitmapFactory.decodeByteArray(image, 0, image.length, opt);
         return bm;
    }
    Là j'ai mis un SampleSize de 8, du coup les images sont très petites.

    En fait le téléchargement à lieu dans l'Adapter, j'ai créer une classe qu'extends CursorAdapter et qui implémente :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    public View getView(int position, View convertView, ViewGroup parent)
    Je n'utilise pas :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    public void bindView(View view, Context context, Cursor cursor)
    ni :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    public View newView(Context context, Cursor cursor, ViewGroup parent)
    Je n'ai pas compris comment elles fonctionnaient, j'ai l'impression qu'il faut mettre 2 fois le même code quasiment.

    Donc dans cet Adapter je regarde un HashMap <String, boolean> la clé en String est l'adresse de l'image et le boolean c'est pour dire si elle est en train d'être téléchargé ou si c'est la première fois qu'on affiche la vignette.

    Et si l'image n'a pas encore été téléchargé je créer une instance de classe qui extends AsyncTask <String, Void, Bitmap>, c'est plutôt sympa car en PostExecute ça setImageBitmap sur une ImageView et les vignettes apparaissent petit à petit.

    Par contre ça créer 36 threads en même temps la première fois

    Et du coup ça peut provoquer :
    java.lang.OutOfMemoryError

    Comment dois-je gérer la mémoire ?
    Est-ce que c'est une mauvaise idée de faire une AsyncTask par vignette ou est-ce que je devrais tout télécharger dans un seul thread ?

    Si vous avez des conseils à me donner, merci de m'en faire part.

    Ici on parle de téléchargé des images :
    http://android-developers.blogspot.f...rformance.html

    Ça fait quelque chose comme ça :
    http://code.google.com/p/android-ima...ownloader.java

  2. #2
    Modérateur
    Avatar de Hizin
    Homme Profil pro
    Développeur mobile
    Inscrit en
    Février 2010
    Messages
    2 180
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France

    Informations professionnelles :
    Activité : Développeur mobile

    Informations forums :
    Inscription : Février 2010
    Messages : 2 180
    Par défaut
    De mon côté, je ferai comme toi, à ceci près que je ferai un manager de DL en prime. Il lance 4 téléchargements (chiffre arbitraire) et, dès que l'un finit et qu'il reste des DL, lancement du/des suivant(s).
    Ca perd en temps de téléchargement (quoi que ... 9 fois moins d'utilisation du réseau, est-ce que les téléchargements n'iront pas plus vite ?), mais ça devrait y gagner en mémoire.
    C'est Android, PAS Androïd, ou Androïde didiou !
    Le premier est un OS, le second est la mauvaise orthographe du troisième, un mot français désignant un robot à forme humaine.

    Membre du comité contre la phrase "ça marche PAS" en titre et/ou explication de problème.

    N'oubliez pas de consulter les FAQ Android et les cours et tutoriels Android

  3. #3
    Membre prolifique
    Avatar de Ryu2000
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2008
    Messages
    10 241
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Décembre 2008
    Messages : 10 241
    Par défaut
    D'accord, je vais essayer de gérer les AsyncTask pour éviter d'en lancer trop en même temps.

    Ou peut être que je vais télécharger toutes les images dans un seul thread avant d'afficher la liste.
    Parce que parfois il y a plusieurs fois la même image et du coup toutes les ImageView ne sont pas à jour.

    Et sinon avec les Bitmap, comment ça fonctionne au niveau de recycle() ?
    Je dois appeler certaines méthode à un moment ?

  4. #4
    Modérateur
    Avatar de Hizin
    Homme Profil pro
    Développeur mobile
    Inscrit en
    Février 2010
    Messages
    2 180
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France

    Informations professionnelles :
    Activité : Développeur mobile

    Informations forums :
    Inscription : Février 2010
    Messages : 2 180
    Par défaut
    Le seul inconvénient du thread unique, c'est que tu va télécharger les images une par une, et donc, rallonger le temps d'attente de l'utilisateur.
    À voir si, dans ton cas, en Wifi et en 3G (si tu n'as pas de contrôle demandant spécifiquement de passer en Wifi pour les affichage) c'est tolérable ou non.

    Si tu as plusieurs fois la même image à afficher, peut-être tenter de les identifier ? Cela te fera ça de moins à télécharger et à créer/allouer.

    Au niveau du recycle, voici ce qu'en dit la doc :
    Citation Envoyé par [url=http://developer.android.com/reference/android/graphics/Bitmap.html#recycle%28%29]Doc[/url]
    Free the native object associated with this bitmap, and clear the reference to the pixel data. This will not free the pixel data synchronously; it simply allows it to be garbage collected if there are no other references. The bitmap is marked as "dead", meaning it will throw an exception if getPixels() or setPixels() is called, and will draw nothing. This operation cannot be reversed, so it should only be called if you are sure there are no further uses for the bitmap. This is an advanced call, and normally need not be called, since the normal GC process will free up this memory when there are no more references to this bitmap.
    Il est donc recommandé de ne pas l'utiliser en temps normal. Personnellement, tant que je ne développe pas spécifiquement pour ICS et supérieur, je préfère l'utiliser (explication en fin).
    Cette méthode n'est a appeler qu'à un seul moment : quand tu es sûr que tu n'auras plus du tout besoin de l'image. Une fois libérée, elle est détruite (enfin ... comme écrit, elle est marquée pour le GC, donc pas libérée dans l'instant, mais tu n'auras plus besoin de t'en soucier).
    Si tu tentes de la ré-utiliser après, tu auras une exception (je ne sais plus laquelle) avec un message assez évocateur "Aren't you trying to use an image thas has been recycled ?".


    De mon côté, je préfère l'utiliser bien qu'il faille faire assez attention à son utilisation (l'exception en question arrive assez facilement si on ne fait pas gaffe ). Quand il y a pas mal de création/destruction d'images, je la pense même obligatoire.

    Tu peux, par exemple, vérifier la mémoire utilisée via Debug.getNativeHeapSize() doc), ainsi que plusieurs outils du DDMS (bon, ceux-là, j'ai plus de mal à les comprendre ... doc).


    Explication ICS :
    Je suis en train de reprendre une appli devant fonctionner à partir de la 2.3. Niveau conso mémoire, c'était un assez gros gouffre au niveau des images (images + textes créé par réflexions). Elle plantait assez vite sous le OutOfMemory après un peu d'utilisation et de visionnement.
    Sous GingerBread, elle consomme beaucoup. Sous ICS, elle consomme presque rien. À priori, ils ont beaucoup amélioré la gestion mémoire des images.
    À la création, sous GingerBread, j'ai 7.3 Mo de mémoire utilisée, sous ICS, j'ai 3.7 Mo.
    Après visionnement de la plupart des images (environs 25), je suis à 16.5 Mo sous Gingerbread et 4.2 Mo sous ICS.

    Remarque : le nombre d'image est toujours à multiplier par 2 : l'image + par réflexion.

    EDIT : à priori, c'est à partir de HoneyComb que la gestion mémoire des images a été améliorée plutôt (test sur tablette équivalent au test sur board ICS).
    C'est Android, PAS Androïd, ou Androïde didiou !
    Le premier est un OS, le second est la mauvaise orthographe du troisième, un mot français désignant un robot à forme humaine.

    Membre du comité contre la phrase "ça marche PAS" en titre et/ou explication de problème.

    N'oubliez pas de consulter les FAQ Android et les cours et tutoriels Android

  5. #5
    Membre prolifique
    Avatar de Ryu2000
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2008
    Messages
    10 241
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Décembre 2008
    Messages : 10 241
    Par défaut
    Pour l'instant mon application est pour Android 2.1, mais en fait elle devra être compatible pour Android 1.6...
    C'est un peu dommage :
    http://developer.android.com/resourc...-versions.html

    En fait l'application smartphone sera la même que l'application tablet, c'est dommage en 3.0 j'aurai peut être moins de problème de mémoire.

    J'essaie de gérer les téléchargements, mais je ne sais pas encore exactement comment faire.

    Je vais récupérer des couples :
    String : adresse de l'image à télécharge
    ImageView : l'ImageView dans laquelle afficher le Bitmap

    Après je ne sais pas vraiment comment faire pour lancer quelques téléchargements et en relancer quand il y en a qui finissent.

  6. #6
    Modérateur
    Avatar de Hizin
    Homme Profil pro
    Développeur mobile
    Inscrit en
    Février 2010
    Messages
    2 180
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France

    Informations professionnelles :
    Activité : Développeur mobile

    Informations forums :
    Inscription : Février 2010
    Messages : 2 180
    Par défaut
    Bon ... là, pour le coup, je ne peux pas t'apporter une autre aide, désolé.

    Toute les archis auxquels je pense et que je tente de mettre en oeuvre pour ce type de solution présente des défauts monstre x)
    À priori, ça fait un poil trop longtemps que je n'ai pas manipulé des Thread et des Handler.
    C'est Android, PAS Androïd, ou Androïde didiou !
    Le premier est un OS, le second est la mauvaise orthographe du troisième, un mot français désignant un robot à forme humaine.

    Membre du comité contre la phrase "ça marche PAS" en titre et/ou explication de problème.

    N'oubliez pas de consulter les FAQ Android et les cours et tutoriels Android

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

Discussions similaires

  1. Réponses: 10
    Dernier message: 18/05/2015, 15h59
  2. Problème de mémoire avec Bitmap (c++/cli)
    Par bonofred dans le forum Windows Forms
    Réponses: 9
    Dernier message: 21/01/2009, 15h58
  3. Problème en mémoire avec des tableaux
    Par dword2add dans le forum C++
    Réponses: 3
    Dernier message: 11/11/2007, 13h36
  4. Réponses: 6
    Dernier message: 19/10/2004, 13h46
  5. Problème de mémoire avec BDE
    Par Machuet dans le forum Bases de données
    Réponses: 3
    Dernier message: 13/07/2004, 10h11

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