Jump to content
Sign in to follow this  
Bertrand31

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

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(); 

Edited by Bertrand31

Share this post


Link to post
Share on other sites

euh je suis pas sûr de moi mais il faut pas mettre un .show() après Toast.makeText(...) ?

Share this post


Link to post
Share on other 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)

Share this post


Link to post
Share on other 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? ...

Share this post


Link to post
Share on other 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 ...

Share this post


Link to post
Share on other 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 :)

Edited by Fluckysan

Share this post


Link to post
Share on other 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

Share this post


Link to post
Share on other 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

Share this post


Link to post
Share on other 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

Share this post


Link to post
Share on other 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 :(

Share this post


Link to post
Share on other 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)

Share this post


Link to post
Share on other sites

Ouais je viens de survoler ton lien, ça peut faire l'affaire je pense.

En plus, je veux juste afficher le même message pour mes différents case:

Donc un seul handler suffira. :D

En tous cas merci à tous !

Share this post


Link to post
Share on other 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

Share this post


Link to post
Share on other 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.

Share this post


Link to post
Share on other 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

Share this post


Link to post
Share on other sites

Cool ce runOnUiThread ! je ne connaissais pas non plus, ça peut grandement simplifier des situations où on est obligés de passer par un Handler et des sendMessage...

Share this post


Link to post
Share on other sites

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();
}

Edited by dawadam

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this  





×
×
  • Create New...