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 :

Thread ou AsyncTask ?


Sujet :

Android

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Inscrit en
    Janvier 2010
    Messages
    55
    Détails du profil
    Informations forums :
    Inscription : Janvier 2010
    Messages : 55
    Par défaut Thread ou AsyncTask ?
    Bonjour,

    Après avoir lu l'article http://mathias-seguy.developpez.com/...async_memleak/ sur les thread et asyncTask, je me sens un peu perdu.

    Je vous explique mon application ainsi que mon problème.

    Mon application fait appel à un webservice sachant que je fais faire appel à une 50ène de méthodes.
    Pour presque toutes ces méthodes, le résultat de l'appel au webservice, va avoir un impact sur l'IHM de l'application (affichage de toast, lancement de nouvelle activity...).
    Il y a une méthode qui est lancé à partir d'un service car elle doit être effectué toutes les 5 secs.

    Au niveau de mon architecture, j'ai une classe "Webservice" où il y a une méthode par chaque requête qui prend comme paramètre, une classe correspondant à la requête et retourne une classe correspondant à la réponse. (Je sais pas si j'ai été bien clair )

    Pour revenir à ma problématique, j'ai d'abord penser utiliser un thread pour chaque appel à ma classe "Webservice". Mais après avoir lu l'article cité plus haut, je me demande si utiliser un asyncTask ne serai pas plus intéressant...


    Drlord

  2. #2
    Membre confirmé
    Inscrit en
    Janvier 2010
    Messages
    55
    Détails du profil
    Informations forums :
    Inscription : Janvier 2010
    Messages : 55
    Par défaut
    Bonjour,

    J'avance un peu dans mon application.
    Par contre j'ai un réel problème avec les Threads, je ne dois pas bien tout comprendre dans leur fonctionnement.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    webServiceManager.request("Authentification", aut);
    String response = webServiceManager.Authentification;
    La méthode "request" de mon manager, gère les différentes requête à mon "webservice".
    Et après je voudrais récupérer la réponse "Authentification" qui a été mise à jour.
    La valeur récupérer ne correspond pas à la requête, ce qui est normal.
    Il y aurai la possibilité d'implémenter un handler, mais si j'ai 3 ou 4 requêtes dans une activity, je ne vais pas implémenter autant d'handler?

    Et puis mon thread n'est pas dans mon activity, donc pas possible d'utiliser un handler.

    Je suis un peu pommé dans tout ça, j'ai sans doute dû ne pas tout comprendre comment implémenter correctement un thread...

    Merci.
    Drlord.

  3. #3
    Expert confirmé

    Homme Profil pro
    Ingénieur systèmes et réseaux
    Inscrit en
    Février 2007
    Messages
    4 253
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur systèmes et réseaux
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Février 2007
    Messages : 4 253
    Billets dans le blog
    3
    Par défaut
    Vu les messages je pense que tu as bien compris ce qu'était un Thread.
    Le probleme c'est qu'on ne peut pas modifier l'UI dans un autre thread que celui de l'UI (le "Main Thread") et on ne peut pas faire d'appels "lents" (réseaux) dans le thread de l'UI.

    Donc effectivement, tout appel à un webservice doit se faire dans un thread à part...

    Un "Handle" est un objet capable d'executer du code dans un autre thread (par le truchement de messages) il faut que le thread soit bien sur preparé pour cela, et ca tombe bien, c'est le cas du main-thread de l'UI...

    Donc l'idée est de créer un Handle dans le thread de l'UI, créer un Thread pour la requete, et lui passer ce handle... A la fin de la requete, le handle est appelé avec la réponse du service...

    Par exemple:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    new Thread(new Runnable() {
       void run() {
           ... appel au webservice
           handle.execute(new Runnable() {
                ... appel au thread UI avec la réponse
           });
       }
    }).run();
    Le probleme de ce code, c'est qu'à moins de faire un classe dédiée d'appels au webservice qui implémente Runnable, il est très compliqué de tout gérer, surtout la durée de vie des objets.
    Dans les cas ou la communication se résume entre le thread UI et une opération simple, il vaut alors largement mieux passer par un AsyncTask qui s'occupera:
    • De gérer le passage des paramètres
    • De faire l'appel dans un thread à part (doInBackground())
    • De faire l'appel retour dans le thread de l'UI (doPostExecute())
    • De gérer le "cancel" eventuel.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    MyWebserviceRequest myRequest = ...;
    new AsyncTask<MyWebserviceRequest,MyWebserviceResponse,Void>() {
        public MyWebserviceResponse doInBackground(MyWebserviceRequest ... params) {
            return params[0].execute();
        }
        public void doPostExecute(MyWebserviceResponse resp) {
           MonActivity.this.onWebserviceResponse(resp);
        }
    }).execute(myRequest);

  4. #4
    Membre confirmé
    Inscrit en
    Janvier 2010
    Messages
    55
    Détails du profil
    Informations forums :
    Inscription : Janvier 2010
    Messages : 55
    Par défaut
    Merci pour tes explications.
    Dans mon service, j'ai essayer les 2 méthodes.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
    	super.onStartCommand(intent, flags, startId);
    	Log.d(TAG, "onStart");
    	timer.scheduleAtFixedRate(new TimerTask() {
    		public void run() {
    			// setConnexionTime();
    			new MyAsyncTask().execute();
    		}
    	}, 0, 5000);
    	return START_NOT_STICKY;
    }
    Mon AsyncTask:
    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
    class MyAsyncTask extends AsyncTask<Void, Void, String> {
     
    		@Override
    		protected String doInBackground(Void... params) {
    			// Requête de set connection time
    			SetconnexionTime sct = new SetconnexionTime();
    			sct.userT = infosSession.idUser;
    			return webservice.SetconnexionTime(sct);
    		}
     
    		@Override
    		protected void onPostExecute(String result) {
     
    			try {
    				result = AESEncrypter.decryptTextFromBase64(result);
    			} catch (AESEncrypterException e) {
    				e.printStackTrace();
    				Log.e(TAG, "AESEncrypterException: " + e.getMessage());
    				error--;
    			}
    			Log.d(TAG, "result: " + result);
    			if (result.equals("1"))
    				error = maxError;
    			else
    				error--;
    			if (error == 0) {
    				errorManager.showToastShort(getBaseContext(), getString(R.string.set_connexion_time_error));
    			}
    		}
    	}
    Mon thread:
    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
    public void setConnexionTime() {
    		Log.d(TAG, "setConnexionTime");
     
    		new Thread(new Runnable() {
     
    			@Override
    			public void run() {
    				// Requête de set connection time
    				SetconnexionTime sct = new SetconnexionTime();
    				sct.userT = infosSession.idUser;
    				String result = webservice.SetconnexionTime(sct);
    				// Envoie de la réponse au handler
    				Message myMessage = myHandler.obtainMessage();
    				Bundle messageBundle = new Bundle();
    				messageBundle.putString("response", result);
    				myMessage.setData(messageBundle);
    				myHandler.sendMessage(myMessage);
    			}
    		}).start();
    	}
    Mon handler:
    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
    Handler myHandler = new Handler() {
     
    		@Override
    		public void handleMessage(Message msg) {
    			String result = msg.getData().getString("response");
    			try {
    				result = AESEncrypter.decryptTextFromBase64(result);
    			} catch (AESEncrypterException e) {
    				e.printStackTrace();
    				Log.e(TAG, "AESEncrypterException: " + e.getMessage());
    				error--;
    			}
    			Log.d(TAG, "result: " + result);
    			if (result.equals("1"))
    				error = maxError;
    			else
    				error--;
    			if (error == 0) {
    				Log.e(TAG, getString(R.string.set_connexion_time_error));
    				errorManager.showToastShort(getBaseContext(), getString(R.string.set_connexion_time_error));
    			}
    		}
    	};
    Tout se passe bien quand je fais ma requête avec mon thread + handler.
    Par contre j'ai une erreur quand j'utilise mon AsyncTask:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    03-14 08:12:09.455: W/dalvikvm(8042): Exception Ljava/lang/RuntimeException; thrown during Landroid/os/AsyncTask;.<clinit>
    03-14 08:12:09.455: W/dalvikvm(8042): threadid=7: thread exiting with uncaught exception (group=0x4001d800)
    03-14 08:12:09.475: E/AndroidRuntime(8042): FATAL EXCEPTION: Timer-0
    03-14 08:12:09.475: E/AndroidRuntime(8042): java.lang.ExceptionInInitializerError
    03-14 08:12:09.475: E/AndroidRuntime(8042): 	at com.camka.service.VamService$2.run(VamService.java:57)
    03-14 08:12:09.475: E/AndroidRuntime(8042): 	at java.util.Timer$TimerImpl.run(Timer.java:289)
    03-14 08:12:09.475: E/AndroidRuntime(8042): Caused by: java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
    03-14 08:12:09.475: E/AndroidRuntime(8042): 	at android.os.Handler.<init>(Handler.java:121)
    03-14 08:12:09.475: E/AndroidRuntime(8042): 	at android.os.AsyncTask$InternalHandler.<init>(AsyncTask.java:421)
    03-14 08:12:09.475: E/AndroidRuntime(8042): 	at android.os.AsyncTask$InternalHandler.<init>(AsyncTask.java:421)
    03-14 08:12:09.475: E/AndroidRuntime(8042): 	at android.os.AsyncTask.<clinit>(AsyncTask.java:152)
    03-14 08:12:09.475: E/AndroidRuntime(8042): 	... 2 more
    Pour infos voici le code de la ligner 57: new MyAsyncTask().execute();

    Je ne vois pas trop ce que j'ai louper dans la construction de mon AsyncTask...

    Merci.
    Drlord.

  5. #5
    Expert confirmé

    Homme Profil pro
    Ingénieur systèmes et réseaux
    Inscrit en
    Février 2007
    Messages
    4 253
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur systèmes et réseaux
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Février 2007
    Messages : 4 253
    Billets dans le blog
    3
    Par défaut
    Tu le fais bien dans le thread de l'UI ?

    Parce que new Handle() ne devrait pas marcher à cet endroit là non plus

    (il n'y pas de mystère hein ! AsyncTask utilise un handle ! )

  6. #6
    Membre confirmé
    Inscrit en
    Janvier 2010
    Messages
    55
    Détails du profil
    Informations forums :
    Inscription : Janvier 2010
    Messages : 55
    Par défaut
    Tout le code que j'ai mis est exécuter dans un service....
    Sachant qu'un service n'a pas d'UI même ma méthode avec un thread ne devrait pas fonctionner il me semble.

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

Discussions similaires

  1. Réponses: 5
    Dernier message: 12/02/2016, 12h01
  2. Synchronisation 2 thread asynctask
    Par jojo_ol76 dans le forum Android
    Réponses: 2
    Dernier message: 26/10/2011, 17h25
  3. Threads (AsyncTask) et rotations d'écran
    Par j0o0 dans le forum Android
    Réponses: 9
    Dernier message: 17/01/2011, 13h22
  4. Thread, Service, AsyncTask, Handler?
    Par androidisme dans le forum Android
    Réponses: 8
    Dernier message: 31/08/2010, 13h25

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