Aller au contenu

[RESOLU] AlertDialog + ProgressDialog + Toast = ***** !!!!


Bertrand31

Recommended Posts

Salut,

Je suis en train de m'arracher les cheveux sur un point qui ne me parait pourtant pas bien compliqué.

Dans mon activité (Uploader) j'affiche tout d'abord un AlertDialog qui m'affiche plusieurs choix pour uploader un photo.

En fonction de l'item sélectionné, j'effectue différentes opérations. Par exemple, dans le cas où "Email" est sélectionné,j'appelle ma fonction sendByEmail au sein d'un ProgressDialog. Ce que j'aimerais, c'est pouvoir afficher un Toast une fois mon ProgressDialog disparu. Et j'ai beau essayé de le déclarer un peu partout, je n'arrive pas à l'afficher...

Des idées ???

Voici le code:

(...)

final CharSequence[] Uploads = { "Email", "HTTP Post", "GAME","Flickr"};

               AlertDialog.Builder alt_bld = new AlertDialog.Builder(Uploader.this);
               alt_bld.setIcon(R.drawable.send);
               alt_bld.setTitle(R.string.send_by);
               alt_bld.setSingleChoiceItems(Uploads, 0,
               new DialogInterface.OnClickListener() {
               public void onClick(DialogInterface dialog, int item) {
                   switch(item){
                   case 0:

// Je vire mon AlertDialog pour pouvoir afficher mon Progress Dialog 
                                        alert.cancel();                     
                       dialogUp = ProgressDialog.show(Uploader.this, "", 
                               getResources().getString(R.string.progress_dialog_http_send), true);
                       new Thread() {
                           public void run(){
                               try{                                
                                   String to = mailSendTo;
                                   sendByMail(filename, to);                               
                                   Toast.makeText(Uploader.this, "Message envoyé !", Toast.LENGTH_SHORT);
                               }catch(Exception e){}
                               dialogUp.dismiss();  
                           }
                       }.start();
                       }                   
                       break;

                   case 1:

                        ( ... )

                            }
               alert.cancel();
               }
               });

               alert = alt_bld.create();
               alert.show(); 

Modifié par Bertrand31
Lien vers le commentaire
Partager sur d’autres sites

En laissant le Toast au sein du thread, rien de s'affiche,

par contre si je le place après le dialogUp.dismiss(), donc si j'ai bien compris, après que mon progressDialog disparaisse, j'ai au moins un plantage de l'application :

Can't create handler inside thread that has not called Looper.prepare()
E/AndroidRuntime( 6664):     at android.os.Handler.(Handler.java:121)
E/AndroidRuntime( 6664):     at android.widget.Toast.(Toast.java:397)
E/AndroidRuntime( 6664):     at android.widget.Toast.makeText(Toast.java:230)
E/AndroidRuntime( 6664):     at com.spotimage.uploader.Uploader$2$2$3.run(Uploader.java:238)

Lien vers le commentaire
Partager sur d’autres sites

bon, honnêtement, j'y connais rien.

mais voilà ce que je ferais:

- déjà avant que tu déplaces le Toast.maketext(...) est-ce qu'il y avait une exception? Tu devrais mettre un log.e(....) dans le catch(exception) {}, t'apprendras ptetre quelque chose...

- j'essaierais de changer le contexte du Toast.makeText(context,...) . Me demande pas pourquoi.

- tu peux essayer d'ajouter Looper.prepare() juste au début du Runnable mais à mon avis c'est un gros outil pour juste un petit Toast

- t'as mis le .show() finalement? ...

Lien vers le commentaire
Partager sur d’autres sites

Bon j'ai remis le Toast après ma fonction sendByMail() (avec .show)

J'ai mis un Log dans la balise exception qui me renvoie la même erreur :


Can't create handler inside thread that has not called Looper.prepare()

Au niveau du contexte j'ai modifié par "getApplicationContext()" , et j'ai la même erreur.

Et puis l'histoire du Looper.prepare() je suis pas sûr d'avoir capté à quoi servait le machin ...

Lien vers le commentaire
Partager sur d’autres sites

C'est un peu mélangé en fait :o

Dans un premier temps, refais l'enchaînement de tes actions :

  • Utilise une Activity avec un thème Dialog que tu lanceras avec startActivityForResult
  • Une fois le choix fait par l'utilisateur dans ta liste, tu retournes un résultats dans ton Activity (et les infos dont tu as besoin)
  • Tu récupère ensuite ton résultat et tes infos via onActivityResult, tu y fais ton switch et ton Thread (il faut le déclarer / construire séparément puis le lancer ici)
  • Dans ton Thread et une fois le traitement fini, tu notifies ton Activity que tout est fini (via un Handler)
  • Dans ton Handler tu t'occupes d'arréter ta ProgressDialog et d'afficher ton Toast (il faut bien le .show() pour l'afficher

C'est la façon de faire que j'utiliserais :)

Modifié par Fluckysan
Lien vers le commentaire
Partager sur d’autres sites

Ouais, ça veut dire que j'ai pas mal de code à revoir... C'est dommage parce que c'était juste pour afficher un petit Toast informant l'utilisateur que sa photo avait bien été uploadée ...

Je vais quand même jeter un œil à ta solution s'il me reste un peu de motiv'

Merci

Lien vers le commentaire
Partager sur d’autres sites

C'est un probleme que je rencontre beaucoup aussi et ton erreur m'est vraiment familière.

J'ai aussi beaucoup de mal à comprendre ces threads avec des alertdialog et un toast qui ne sait pas s'afficher en meme temps!

C'est assez casse-tête et pas vraiment intuitif

Lien vers le commentaire
Partager sur d’autres sites

Il ne faut pas que tu te démotives !

Si tu y va petit à petit ça va aller et tu vas voir que ça sera beaucoup plus clair après :)

Je précise que la façon de faire que je t'ai indiqué, c'est une des façon possible et que toute ses modifications ne sont pas uniquement pour afficher le Toast mais pour apporter de la clarté à ton code et se faisant l'affichage du Toast est beaucoup plus simple !

Je te conseille de jeter un oeil à ce tuto : http://www.helloandroid.com/tutorials/using-threads-and-progressdialog

Lien vers le commentaire
Partager sur d’autres sites

Oui je comprends, c'est juste que c'est une application que je développe en stage, ça fait 1 mois que je suis dessus, et là je voulais juste finaliser esthétiquement. Ça m'embête un peu de revoir ce gros bout de code sachant que j'ai une démo Lundi :(

Lien vers le commentaire
Partager sur d’autres sites

Hum je comprends :/

On ne peut pas afficher de Toast dans un Thread, d'où le message d'erreur

Dans l'urgence tu peux prendre seulement la partie Handler du tuto :

  • Créer un Handler avec ton Toast.show() dans son handleMessage
  • Remplace ton Toast.show() de ton Thread par un tonHandler.sendEmptyMessage(0)

Tu peux ensuite adapter ton Handler avec un switch suivant ce que tu lui envois pour afficher différent message

Ca devrait faire l'affaire pour ta démo (bout de scotch lol)

Lien vers le commentaire
Partager sur d’autres sites

Hum...

J'arrive apres la bataille, et comme j'ai juste survolé, je peux me planter, mais :

Tout ce qui est UI doit se faire dans le thread principal. Donc est-ce que ton probleme n'est pas juste que tu essaye de lancer un toast dans un thread non principal ( et que cette limitation s'applique aux toasts, ce dont je ne suis pas entierement persuadé ).

La bonne nouvelle, c'est que si c'est ca, c'est pas mal prévu par Android : ils ont fait une fonction spéciale 'runOnUiThread' pour lancer une commande dans le bon thread.

donc peut etre que qq chose de ce gout la marcherait :

runOnUiThread(new Runnable() {

public void run() {

Toast.makeText(this, "pouetpouet", Toast.LENGTH_SHORT).show();

}

});

Emmanuel / Alocaly

Lien vers le commentaire
Partager sur d’autres sites

Hallelujah mes frères !! :D

Effectivement Alocaly, tu as trouvé la solution à mon problème !!!

Je ne connaissais pas l'existence de runOnUiThread .

Ça m'ouvre pas mal d'horizon sur des améliorations d'ergonomie .

J'édite le sujet de ce pas.

Merci bien.

Lien vers le commentaire
Partager sur d’autres sites

Ah ??? :)

Bon, ben c'est super !!

En meme temps, je ne comprends pas tout moi : hier, juste apres avoir écrit ce message, j'ai modifié une appli à moi en remplacant un toast par la mise à jour d'une textView : alors que le toast marchait sans soucis, la mise à jour du textview ne marchait pas, et j'ai du mettre un runOnUiThread pour le faire marcher.

Alors qu'avec mon toast, je n'en avais pas besoin... ( et du coup, je m'etais dit que je m'etais planté avec mon post :) )

Bon, ben le principal c'est que ca marche chez tout le monde, non :) ??

Emmanuel / Alocaly

Lien vers le commentaire
Partager sur d’autres sites

  • 1 year later...

Salut

Merci pour le "runOnUiThread" que je ne connaissais pas non-plus.

Jusqu’à maintenant j'utilisais uniquement le Handler.Callback qui fonctionne bien d’ailleurs.

Il faut bien ce faire au fonctionnement Android :)

Mais, même avec Handler, on peut tomber sur ce message d'erreur :

// Can't create handler inside thread that has not called Looper.prepare()

En fait, on cré le handler comme ça :

Handler handler = new Handler(callback); // callback est un Handler.Callback

On fait sa dans le UI et on peut ensuite transmettre le Handler dans n'importe quel Thread.

En retour il suffit d'utiliser :

handler.sendMessage(message); // message est un android.os.Message

Et donc la méthode du Callback sera appelée (qui est l'interface à implémenter dans notre activité)

C'est pas simple, mais c'est comme ça...

Sinon il y a cette fameuse méthode runOnUiThread pour ceux qui ne veulent pas y penser -_-

Au cas où un exemple d'une méthode static pour faire un traitement dans un autre Thread et renvoyer la réponse à un callback :

public static void getInternetPage(Handler.Callback callback, final int code) {
 // handler (ne surtout pas créer dans l'autre Thread, il faut que ce soit commandé par l'UI)
 final android.os.Handler handler = new Handler(callback);
 // thread
 new Thread(new Runnable() {
  @Override
  public void run() {
 // l'action qui prend du temps et donc requière le Thread
Page page = connectionPourTelechargerUnePage();
// envoi le retour (code retour pratique si plusieurs callback)
android.os.Message msg = new android.os.Message();
msg.what = code;
msg.obj = page;
handler.sendMessage(msg);
  }
 }).start();
}

Modifié par dawadam
Lien vers le commentaire
Partager sur d’autres sites

Rejoignez la conversation

Vous pouvez poster maintenant et vous enregistrez plus tard. Si vous avez un compte, connectez-vous maintenant pour poster.

Invité
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Répondre à ce sujet…

×   Collé en tant que texte enrichi.   Coller en tant que texte brut à la place

  Seulement 75 émoticônes maximum sont autorisées.

×   Votre lien a été automatiquement intégré.   Afficher plutôt comme un lien

×   Votre contenu précédent a été rétabli.   Vider l’éditeur

×   Vous ne pouvez pas directement coller des images. Envoyez-les depuis votre ordinateur ou insérez-les depuis une URL.

×
×
  • Créer...