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 :

Gestion image et fuite mémoire


Sujet :

Android

  1. #21
    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,

    Mais il y a bien que l'UIThread qui peut modifie les éléments de la vue ? Normalement si j'essaye de changer un élément contenu dans ma view depuis un autre thread, je devrai recevoir une erreur de ce type là
    Oui , tu as juste .

    non ? Je pensais que le Handler était une sorte d'observer qui faisait la liaison entre l'UIThread et les autres Thread et donc que son code était plus ou moins rattaché à celui de l'UIThread.
    Le Handler
    A Handler allows you to send and process Message and Runnable objects associated with a thread's MessageQueue. Each Handler instance is associated with a single thread and that thread's message queue. When you create a new Handler, it is bound to the thread / message queue of the thread that is creating it -- from that point on, it will deliver messages and runnables to that message queue and execute them as they come out of the message queue.
    http://developer.android.com/referen...s/Handler.html


    L'utilisation de la fonction runOnUiThread se fait directement dans le thread
    Oui c'est pour préciser à ton thread que tu aimerais qu'il tourne directement sur l'UIThread ce qui n'est pas le cas si tu utilises la procédure run .

    Par contre cela implique qu'il utilise déjà un thread existant (UIThread) et non un nouveau thread .

    oui alors je le fais dans le Handler ? Si c'est la première solution est la bonne, les Handler ne servent à rien au final s'ils ne peuvent pas interagir sur la vue.
    Si ils servent à plein de chose pas seulement pour l'affichage de la vue .
    La gestion des messages (envoie, réception), les observers sur le changement de donnée , ...


    Par contre j'ai un plus de mal à voir l'utilisation de invalidate(), postInvalidate(). D'après ce que j'ai compris, on surcharge la méthode invalidate pour qu'elle fasse ce que l'on veut et après on fait myImageView.postInvalidate(); pour appeler la méthode. Je ne vois pas la différence qu'il y a entre les 2 méthodes.
    Tu peux utiliser les handlers ou the thread (run), par contre comme tu l'as souligné il faudra utilisé le postinvalidate sur toutes modifications de la vue , pour indiquer que cette méthode doit bien se faire dans l'UIThread et non dans le thread actuel .

    En gros
    invalidate -> appel d'un UIThread
    postinvalidate-> appel d'un Non UI Thread

    public void postInvalidate ()
    Since: API Level 1

    Cause an invalidate to happen on a subsequent cycle through the event loop. Use this to invalidate the View from a non-UI thread.
    See Also

    * invalidate()
    tu as les autres méthodes à ce lien
    http://developer.android.com/guide/t...d-threads.html

    * Activity.runOnUiThread(Runnable)
    * View.post(Runnable)
    * View.postDelayed(Runnable, long)

    Sinon j'ai fait le test ce matin. Effectivement ca marche bien mieux quand je recycle l'image juste avant d'insérer la nouvelle, sauf dans le cas ou ce sont de très grande image... En effet il n'y a pas la place pour deux images sur la mémoire de l'application. Je vais être obligé de recycler mon image avant de télécharger la nouvelle.
    ,essayes alors de réduire la taille de la première avant de télécharger la seconde, à mois que tu ne sois obligé de garder la qualité de l'image . Sinon c'est là

    http://developer.android.com/referen...,%20boolean%29

    Au pire tu peux toujours la compresser,
    http://developer.android.com/referen...utputStream%29
    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.

  2. #22
    Membre confirmé
    Profil pro
    Inscrit en
    Mars 2011
    Messages
    322
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2011
    Messages : 322
    Points : 494
    Points
    494
    Par défaut
    C'est de nouveau moi !!

    Je ne suis pas sur d'avoir tout bien compris, mais j'ai essayé de mettre en application les choses vu sur ce sujet.

    J'ai regardé ce lien http://android-developers.blogspot.c...threading.html et vu qu'avec les Thread je n'ai pas vraiment d'accroche, j'ai décidé de tenter avec les AsyncTask même si on m'avait dit que ça s'utilisait plutôt dans les services, est ce vrai ?

    Bien évidemment cela ne marche pas, ca serait trop beau...
    Voici mon code : (j'ai enlevé ce qui est dans le try car c'est la même chose depuis le début.
    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
    private class DownloadImageTask extends AsyncTask<String,Void,Bitmap> {
     
    		@Override
    		protected Bitmap doInBackground(String... urls) {
    			Bitmap b = null;
    			try {
    				//Récupération image
    			} catch (IOException e) {
    				e.printStackTrace();
    			}  catch (OutOfMemoryError e) {
    				Log.d("Pas assez de mémoire", "dommage");
    			}
    			return b;
    		}
     
    		@Override
    		protected void onPostExecute(Bitmap result) {
    			BitmapDrawable dw = (BitmapDrawable) myImageView.getDrawable();
    			if (dw != null) {
    				Bitmap b = dw.getBitmap();
    				if (b != null)
    					b.recycle();
    			}	
    			myImageView.setImageBitmap(result);
    		}
     
    		@Override
    		protected void onPreExecute() {
     
    		}
     
     
    	}
    Donc là, ça marche, merci j'y serais jamais arriver sans toi, mais il reste quand même un problème. Je télécharge des images vraiment grosse. L'application ne peut pas en avoir plus d'une à la fois. Du coup quand je télécharge une nouvelle photo vu qu'il n'a pas encore recyclé l'ancienne, il passe dans l'exception outOfMemoryError.

    Je vais vous expliquer toute ma démarche.
    J'ai décidé de faire le recycle dans le onPreExecute. Et là gros crash
    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
    05-11 15:15:06.316: ERROR/AndroidRuntime(31802): FATAL EXCEPTION: main
    05-11 15:15:06.316: ERROR/AndroidRuntime(31802): java.lang.RuntimeException: Canvas: trying to use a recycled bitmap android.graphics.Bitmap@405a8440
    05-11 15:15:06.316: ERROR/AndroidRuntime(31802):     at android.graphics.Canvas.throwIfRecycled(Canvas.java:955)
    05-11 15:15:06.316: ERROR/AndroidRuntime(31802):     at android.graphics.Canvas.drawBitmap(Canvas.java:1044)
    05-11 15:15:06.316: ERROR/AndroidRuntime(31802):     at android.graphics.drawable.BitmapDrawable.draw(BitmapDrawable.java:325)
    05-11 15:15:06.316: ERROR/AndroidRuntime(31802):     at android.widget.ImageView.onDraw(ImageView.java:872)
    05-11 15:15:06.316: ERROR/AndroidRuntime(31802):     at android.view.View.draw(View.java:6880)
    05-11 15:15:06.316: ERROR/AndroidRuntime(31802):     at android.view.ViewGroup.drawChild(ViewGroup.java:1646)
    05-11 15:15:06.316: ERROR/AndroidRuntime(31802):     at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1373)
    05-11 15:15:06.316: ERROR/AndroidRuntime(31802):     at android.view.ViewGroup.drawChild(ViewGroup.java:1644)
    05-11 15:15:06.316: ERROR/AndroidRuntime(31802):     at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1373)
    05-11 15:15:06.316: ERROR/AndroidRuntime(31802):     at android.view.View.draw(View.java:6883)
    05-11 15:15:06.316: ERROR/AndroidRuntime(31802):     at android.widget.FrameLayout.draw(FrameLayout.java:357)
    05-11 15:15:06.316: ERROR/AndroidRuntime(31802):     at android.view.ViewGroup.drawChild(ViewGroup.java:1646)
    05-11 15:15:06.316: ERROR/AndroidRuntime(31802):     at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1373)
    05-11 15:15:06.316: ERROR/AndroidRuntime(31802):     at android.view.View.draw(View.java:6883)
    05-11 15:15:06.316: ERROR/AndroidRuntime(31802):     at android.widget.FrameLayout.draw(FrameLayout.java:357)
    05-11 15:15:06.316: ERROR/AndroidRuntime(31802):     at com.android.internal.policy.impl.PhoneWindow$DecorView.draw(PhoneWindow.java:1862)
    05-11 15:15:06.316: ERROR/AndroidRuntime(31802):     at android.view.ViewRoot.draw(ViewRoot.java:1522)
    05-11 15:15:06.316: ERROR/AndroidRuntime(31802):     at android.view.ViewRoot.performTraversals(ViewRoot.java:1258)
    05-11 15:15:06.316: ERROR/AndroidRuntime(31802):     at android.view.ViewRoot.handleMessage(ViewRoot.java:1859)
    05-11 15:15:06.316: ERROR/AndroidRuntime(31802):     at android.os.Handler.dispatchMessage(Handler.java:99)
    05-11 15:15:06.316: ERROR/AndroidRuntime(31802):     at android.os.Looper.loop(Looper.java:130)
    05-11 15:15:06.316: ERROR/AndroidRuntime(31802):     at android.app.ActivityThread.main(ActivityThread.java:3683)
    05-11 15:15:06.316: ERROR/AndroidRuntime(31802):     at java.lang.reflect.Method.invokeNative(Native Method)
    05-11 15:15:06.316: ERROR/AndroidRuntime(31802):     at java.lang.reflect.Method.invoke(Method.java:507)
    05-11 15:15:06.316: ERROR/AndroidRuntime(31802):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
    05-11 15:15:06.316: ERROR/AndroidRuntime(31802):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
    05-11 15:15:06.316: ERROR/AndroidRuntime(31802):     at dalvik.system.NativeStart.main(Native Method)
    Je suis repartis sur le premier code avec tout dans le onPostExecute. Vu que je passais dans le catch, le onPostExecute recevait null en valeur de Bitmap, ce qui avait pour effet de supprimer la photo (normal). Si je recliquais sur l'image il arrivait à la télécharger vu qu'il y avait de l'espace. Mais c'est pas top de devoir cliquer deux fois.

    Donc j'ai tenté un truc et là je vous jure que je ne vous mens pas, que c'est pas le fruit du hasard. J'ai mis ça
    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
    @Override
    		protected void onPostExecute(Bitmap result) {
    			myImageView.setImageBitmap(result);
     
    		}
     
    		@Override
    		protected void onPreExecute() {
    			BitmapDrawable dw = (BitmapDrawable) myImageView.getDrawable();
    			if (dw != null) {
    				Bitmap b = dw.getBitmap();
    				if (b != null)
    					b.recycle();
    			}
    			myImageView.setImageBitmap(null);
    		}
    Et là ça marche... Mais mais pourquoi ??
    Je ne comprends vraiment pas ce qui se passe.


    Merci encore de m'avoir aidé. Je range cette discussion dans mes favoris, comme si un jour j'ai trop le moral je viendrai la relire

  3. #23
    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 là ça marche... Mais mais pourquoi ??
    Je ne comprends vraiment pas ce qui se passe.
    Hmm , tu ne peux pas recycler ta bitmap tant que tu n'as pas changer celle-ci .
    Sinon elle perds les données et elle ne sait pas où les retrouver.
    Donc cela marche dans ton deuxième cas car tu changes la bitmap de suite après l'avoir recycler .

    par contre juste une question quand tu parles de charger des images vraiment grosses c'est quelle taille à peu près ?
    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.

  4. #24
    Membre confirmé
    Profil pro
    Inscrit en
    Mars 2011
    Messages
    322
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2011
    Messages : 322
    Points : 494
    Points
    494
    Par défaut
    Je me suis peut être un peu emporté sur le terme "vraiment grosses" . Elles font plus d'un Mo . Mais pour moi elles grosses car le téléchargement prend du temps.
    Ok merci pour ta réponse

  5. #25
    Membre du Club
    Profil pro
    Inscrit en
    Juin 2005
    Messages
    65
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2005
    Messages : 65
    Points : 52
    Points
    52
    Par défaut
    Je me permet de faire remonter cette question car j'ai le même problème que je n'arrive absolument pas à resoudre

    Voici un bout de ma classe permettant de redimensionner une image. Pour permettre de se déplacer sur une image plus grande que l'écran

    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
    50
     
    public class ResizableBitmap
    {
    	// bitmap large enough to be scrolled
    	private static Bitmap bmLargeImage; 
     
    	// zoom leve
    	private float zoomLevel;
     
        public ResizableBitmap( Context context, Bitmap drawable, float zoomLevel)
        {
            // load bitmap
            bmLargeImage = drawable;
    		this.zoomLevel = zoomLevel;
     
            // initialiastion par defaut
            Display display = ( (WindowManager) context.getSystemService( Context.WINDOW_SERVICE ) ).getDefaultDisplay();
            onSizeChanged( display.getWidth(), display.getHeight(), 0, 0 );
        }
     
    	public void onSizeChanged( int w, int h, int oldw, int oldh )
        {
    		... some code
     
            // redimensionnement
            bmLargeImage = resize( bmLargeImage, w );
     
    		... some code
    	}
     
    	private Bitmap resize( Bitmap bm, int w )
        {
            // initial size
            int width = bm.getWidth();
            int height = bm.getHeight();
     
            // zoom level (zoom is always up to 1)
            w *= zoomLevel;
     
            // scale
            float scaleWidth = ( (float) w ) / width;
            float scaleHeight = ( (float) w ) / width;
     
            Matrix matrix = new Matrix();
            matrix.postScale( scaleWidth, scaleHeight );
            Bitmap resizedBitmap = Bitmap.createBitmap( bm, 0, 0, width, height, matrix, true );
     
            return resizedBitmap;
        }
    }
    Mais j'ai une outofmemory erreur sur certain téléphone. Uniquement ceux avec un heapspace de 16Mb.

    Une idée ?

  6. #26
    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,

    Est ce que tu recycle tes bitmaps que tu n'utilises plus ?
    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.

+ Répondre à la discussion
Cette discussion est résolue.
Page 2 sur 2 PremièrePremière 12

Discussions similaires

  1. Gestion images opencv python par mémoire partagée
    Par Tchef dans le forum Bibliothèques tierces
    Réponses: 0
    Dernier message: 12/08/2009, 15h12
  2. [tomcat][memoire] java.net.URL et fuite mémoire
    Par Seiya dans le forum Tomcat et TomEE
    Réponses: 6
    Dernier message: 09/03/2009, 10h41
  3. Réponses: 2
    Dernier message: 27/12/2004, 09h23
  4. [SWT]SWT et fuite mémoire(ou pas)
    Par menuge dans le forum SWT/JFace
    Réponses: 2
    Dernier message: 22/06/2004, 21h40
  5. [debug] fuites mémoires
    Par tmonjalo dans le forum C
    Réponses: 3
    Dernier message: 28/07/2003, 17h20

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