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 :

Comment éviter NetworkOnMainThreadException


Sujet :

Android

  1. #1
    Futur Membre du Club
    Homme Profil pro
    Inscrit en
    Juin 2013
    Messages
    7
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations forums :
    Inscription : Juin 2013
    Messages : 7
    Points : 5
    Points
    5
    Par défaut Comment éviter NetworkOnMainThreadException
    Bonjour à tous,
    Je n'arrive pas à me dépétrer de cette erreur NetworkOnMainThreadException. Biensur, je sais qu'il ne faut pas faire du Network depuis le mainThread. J'ai mis mon code de test dans un Thread, et cela fonctionne.

    Mais en fait je dois communiquer avec une api SOAP web, et donc effectuer plusieurs requêtes à la suite, et ce, de façons conditionnelles. Ex :

    if (! identified) {
    .. httpRequest1 : login
    } else {
    .. if (currentDB == "toto") {
    .... httpRequest 2;
    .... httpRequest 3;
    }

    donc si je commence a jouer avec des Handler et des Runnables, je vais en faire pleins... c'est pourri !

    Je ne vois pas comment faire...

    Pouvez-vous m'aider ?

  2. #2
    Membre éprouvé
    Profil pro
    Inscrit en
    Janvier 2011
    Messages
    757
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2011
    Messages : 757
    Points : 968
    Points
    968
    Par défaut
    Une solution simple est d'utiliser les AsyncTask.
    Elles séparent bien les tâches à effectuer dans le UiThread et celles à faire en arrière plan.

    La méthode doInBackground comme son nom l'indique, est l'endroit où tu peux faire tes requêtes web.
    Et onPostExecute te permet de modifier et d'intérragir avec le Thread graphique lorsque ta tâche est finie.

  3. #3
    Futur Membre du Club
    Homme Profil pro
    Inscrit en
    Juin 2013
    Messages
    7
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations forums :
    Inscription : Juin 2013
    Messages : 7
    Points : 5
    Points
    5
    Par défaut Toujours pas
    Merci pour ta réponse rapide. J'ai essayé sans succès :
    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
    		tv = (TextView) findViewById(R.id.textView1);
    		button = (Button) findViewById(R.id.button1);
    		button.setOnClickListener(new View.OnClickListener() {
    			public void onClick(View v) {
    				class Sess extends AsyncTask<Void, Integer, Long> {
    					protected Long doInBackground(Void... arg0) {
    						linkSession.isSessionOpened();
    						linkSession.executeBatch(false, null, null);
    						return null;
    					}
     
    					protected void onPostExecute(Long result) {
    						tv.setText(linkSession.getSoapResponse());
    					}
    				}
    				new Sess().execute();
    			}
    		});
    Mon isSessionOpened construit simplement la requête SOAP dans un String.
    Mon executeBatch effectue le post HTTP de la requête sur le serveur, c'est à ce moment que çà plante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    06-11 14:16:40.035: E/AndroidRuntime(2189): Caused by: java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()

    C'est pas très propre, désolé, pour le moment je valide le process avant de faire propre.

  4. #4
    Membre éprouvé
    Profil pro
    Inscrit en
    Janvier 2011
    Messages
    757
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2011
    Messages : 757
    Points : 968
    Points
    968
    Par défaut
    En effet, ce n'est pas propre, et ça te fait faire des erreurs
    La classe devrait être définie à l'exterieur du onClick.

  5. #5
    Futur Membre du Club
    Homme Profil pro
    Inscrit en
    Juin 2013
    Messages
    7
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations forums :
    Inscription : Juin 2013
    Messages : 7
    Points : 5
    Points
    5
    Par défaut
    Oui, mais j'ai beau la sortir du onClick... ça plante toujours :

    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
    public class MainTestSOAP extends Activity {
    	private TextView tv;
    	private Button button;
    	private TLinkSession linkSession = new TLinkSession();
     
    	class Sess extends AsyncTask<Void, Integer, Long> {
    		protected Long doInBackground(Void... arg0) {
    //			Looper.prepare();
    			linkSession.isSessionOpened();
    			linkSession.executeBatch(false, null, null);
    			return null;
    		}
     
    		protected void onPostExecute(Long result) {
    			tv.setText(linkSession.getSoapResponse());
    		}
    	}
     
    	@Override
    	protected void onCreate(Bundle savedInstanceState) {
    		super.onCreate(savedInstanceState);
    		setContentView(R.layout.activity_main_test_soap);
     
    		tv = (TextView) findViewById(R.id.textView1);
    		button = (Button) findViewById(R.id.button1);
    		button.setOnClickListener(new View.OnClickListener() {
    			public void onClick(View v) {
    				new Sess().execute();
    			}
    		});
    	}
    }
    J'ai tenté de mettre le Looper.prepare(); mais je ne vois pas pourquoi ni comment cela fonctionne...

  6. #6
    Expert éminent

    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
    Points : 7 618
    Points
    7 618
    Billets dans le blog
    3
    Par défaut
    Non non le Looper.prepare() permet de créer une pile de message, chose que le thread UI a déjà.

    Là on dirait que le onClick() est reçu dans un autre thread que celui de l'UI, ce qui est très étrange !

    On peut avoir la stacktrace complète ? (et pas seulement l'exception) ?
    N'oubliez pas de cliquer sur mais aussi sur si un commentaire vous a été utile !
    Et surtout

  7. #7
    Futur Membre du Club
    Homme Profil pro
    Inscrit en
    Juin 2013
    Messages
    7
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations forums :
    Inscription : Juin 2013
    Messages : 7
    Points : 5
    Points
    5
    Par défaut
    Voilà :

    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
    06-11 14:58:10.079: W/dalvikvm(3176): threadid=11: thread exiting with uncaught exception (group=0x40a71930)
    06-11 14:58:10.096: E/AndroidRuntime(3176): FATAL EXCEPTION: AsyncTask #1
    06-11 14:58:10.096: E/AndroidRuntime(3176): java.lang.RuntimeException: An error occured while executing doInBackground()
    06-11 14:58:10.096: E/AndroidRuntime(3176): 	at android.os.AsyncTask$3.done(AsyncTask.java:299)
    06-11 14:58:10.096: E/AndroidRuntime(3176): 	at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:352)
    06-11 14:58:10.096: E/AndroidRuntime(3176): 	at java.util.concurrent.FutureTask.setException(FutureTask.java:219)
    06-11 14:58:10.096: E/AndroidRuntime(3176): 	at java.util.concurrent.FutureTask.run(FutureTask.java:239)
    06-11 14:58:10.096: E/AndroidRuntime(3176): 	at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230)
    06-11 14:58:10.096: E/AndroidRuntime(3176): 	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1080)
    06-11 14:58:10.096: E/AndroidRuntime(3176): 	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573)
    06-11 14:58:10.096: E/AndroidRuntime(3176): 	at java.lang.Thread.run(Thread.java:856)
    06-11 14:58:10.096: E/AndroidRuntime(3176): Caused by: java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
    06-11 14:58:10.096: E/AndroidRuntime(3176): 	at android.os.Handler.<init>(Handler.java:197)
    06-11 14:58:10.096: E/AndroidRuntime(3176): 	at android.os.Handler.<init>(Handler.java:111)
    06-11 14:58:10.096: E/AndroidRuntime(3176): 	at com.gringo.soapproxy.HTTPConnector.<init>(HTTPConnector.java:23)
    06-11 14:58:10.096: E/AndroidRuntime(3176): 	at com.gringo.soapproxy.TLinkSession.executeBatch(TLinkSession.java:19)
    06-11 14:58:10.096: E/AndroidRuntime(3176): 	at com.gringo.soapproxy.MainTestSOAP$2$Sess.doInBackground(MainTestSOAP.java:44)
    06-11 14:58:10.096: E/AndroidRuntime(3176): 	at com.gringo.soapproxy.MainTestSOAP$2$Sess.doInBackground(MainTestSOAP.java:1)
    06-11 14:58:10.096: E/AndroidRuntime(3176): 	at android.os.AsyncTask$2.call(AsyncTask.java:287)
    06-11 14:58:10.096: E/AndroidRuntime(3176): 	at java.util.concurrent.FutureTask.run(FutureTask.java:234)
    06-11 14:58:10.096: E/AndroidRuntime(3176): 	... 4 more
    06-11 14:58:12.326: I/Process(3176): Sending signal. PID: 3176 SIG: 9

  8. #8
    Expert éminent

    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
    Points : 7 618
    Points
    7 618
    Billets dans le blog
    3
    Par défaut
    Ben voilà... on a la réponse.... com.gringo.soapproxy

    Je ne sais pas d'ou ca vient, mais le truc crée déjà un handler (probablement pour lancer un thread ?)... à mon avis il nous manque des infos sur la librairie soap utilisée, sa documentation (si il y a un handler, la gestion des threads doit être intégrée), etc...
    N'oubliez pas de cliquer sur mais aussi sur si un commentaire vous a été utile !
    Et surtout

  9. #9
    Futur Membre du Club
    Homme Profil pro
    Inscrit en
    Juin 2013
    Messages
    7
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations forums :
    Inscription : Juin 2013
    Messages : 7
    Points : 5
    Points
    5
    Par défaut
    You good men !

    Suffisait de lire les logs en fait... pauvre de moi.
    com.gringo c'est moi, c'est mon api SOAP. En fait j'avais fait 2 méthodes pour faire la requête : une synchrone et une asynchrone. La version asynchrone utilise un handler, que j'avais instancié dans la classe et non dans la méthode... oups.

    J'ai encore pas mal de questions futures, mais merci beaucoup pour aide !

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

Discussions similaires

  1. Comment éviter le lancement automatique de CBuilder
    Par Xavier dans le forum C++Builder
    Réponses: 3
    Dernier message: 26/01/2005, 17h35
  2. Comment éviter les doublons dans ma table
    Par einegel dans le forum Bases de données
    Réponses: 3
    Dernier message: 09/11/2004, 12h18
  3. [TEdit] Comment éviter le bip ?
    Par portu dans le forum Composants VCL
    Réponses: 4
    Dernier message: 01/10/2004, 12h01
  4. Réponses: 4
    Dernier message: 28/07/2004, 10h42
  5. [eclipse 2.1][compilation] Comment éviter...
    Par ftrifiro dans le forum Eclipse Java
    Réponses: 3
    Dernier message: 29/06/2004, 16h16

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