web-dev-qa-db-fra.com

Comment afficher un Toast dans Android AsyncTask?

J'essaie d'afficher Toast dans ma classe initial_background étendue avec AsyncTask<URL, Integer, Long>. Je reçois cette erreur dans logcat.

public class InitialBackgroundTask extends AsyncTask<URL, Integer, Long> {

    @Override
    protected Long doInBackground(URL... params) {
        // TODO Auto-generated method stub
        show a = new show();
        a.loop();
        return null;
    }

public class show {

    void loop()
    {
        for(int i=0; i<10; i++)
        {
            Toast.makeText(MainActivity.me, "test", Toast.LENGTH_LONG).show();
        }
    }
}

C'est l'exception:

05-30 12:08:12.641: E/AndroidRuntime(30840): FATAL EXCEPTION: AsyncTask #1
05-30 12:08:12.641: E/AndroidRuntime(30840): Java.lang.RuntimeException: An error occured while executing doInBackground()
05-30 12:08:12.641: E/AndroidRuntime(30840):    at Android.os.AsyncTask$3.done(AsyncTask.Java:278)
05-30 12:08:12.641: E/AndroidRuntime(30840):    at Java.util.concurrent.FutureTask$Sync.innerSetException(FutureTask.Java:273)
05-30 12:08:12.641: E/AndroidRuntime(30840):    at Java.util.concurrent.FutureTask.setException(FutureTask.Java:124)
05-30 12:08:12.641: E/AndroidRuntime(30840):    at Java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.Java:307)
05-30 12:08:12.641: E/AndroidRuntime(30840):    at Java.util.concurrent.FutureTask.run(FutureTask.Java:137)
05-30 12:08:12.641: E/AndroidRuntime(30840):    at Android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.Java:208)
05-30 12:08:12.641: E/AndroidRuntime(30840):    at Java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.Java:1076)
05-30 12:08:12.641: E/AndroidRuntime(30840):    at Java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.Java:569)
05-30 12:08:12.641: E/AndroidRuntime(30840):    at Java.lang.Thread.run(Thread.Java:856)
05-30 12:08:12.641: E/AndroidRuntime(30840): Caused by: Java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
05-30 12:08:12.641: E/AndroidRuntime(30840):    at Android.os.Handler.<init>(Handler.Java:121)
05-30 12:08:12.641: E/AndroidRuntime(30840):    at Android.widget.Toast$TN.<init>(Toast.Java:317)
05-30 12:08:12.641: E/AndroidRuntime(30840):    at Android.widget.Toast.<init>(Toast.Java:91)
05-30 12:08:12.641: E/AndroidRuntime(30840):    at Android.widget.Toast.makeText(Toast.Java:233)
05-30 12:08:12.641: E/AndroidRuntime(30840):    at   com.example.toast.show.loop(show.Java:11)
05-30 12:08:12.641: E/AndroidRuntime(30840):    at com.example.toast.InitialBackgroundTask.doInBackground(InitialBackgroundTask.Java:13)
05-30 12:08:12.641: E/AndroidRuntime(30840):    at com.example.toast.InitialBackgroundTask.doInBackground(InitialBackgroundTask.Java:1)
05-30 12:08:12.641: E/AndroidRuntime(30840):    at Android.os.AsyncTask$2.call(AsyncTask.Java:264)
05-30 12:08:12.641: E/AndroidRuntime(30840):    at Java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.Java:305)
05-30 12:08:12.641: E/AndroidRuntime(30840):    ... 5 more

Le code ci-dessus montre toute l'histoire. En fait, je veux montrer un toast dans la méthode doInBackground

18
Noman Dilawar

Vous ne pouvez pas mettre à jour l'interface utilisateur sur le fil d'arrière-plan. doInBackground() est invoqué sur le thread d'arrière-plan. Vous devez mettre à jour l'interface utilisateur sur le fil de l'interface utilisateur.

      runOnUiThread(new Runnable(){

          @Override
          public void run(){
            //update ui here
            // display toast here 
          }
       });

onPreExecute(), onPostExecute(Result), sont appelés sur le thread d'interface utilisateur. Vous pouvez donc afficher le pain grillé ici.

onProgressUpdate(Progress...), appelé sur le thread d'interface utilisateur après un appel à publishProgress(Progress...) peut être utilisé pour animer une barre de progression ou afficher les journaux dans un champ de texte.

Le résultat du calcul de doInBackground() est un paramètre de onPostExecute(Result) alors renvoyez le résultat en doinBackground() et affichez votre pain grillé en onPostExecute(Result)

Vous pouvez également utiliser un gestionnaire comme suggéré par @Stine Pike

Pour plus de clarté, consultez le lien ci-dessous sous le sujet: Les 4 étapes.

http://developer.Android.com/reference/Android/os/AsyncTask.html

27
Raghunandan

Créez un objet de gestionnaire et exécutez tous vos messages Toast à l'aide de cet objet.

@Override
protected Void doInBackground(Void... params) {
    Handler handler =  new Handler(context.getMainLooper());
    handler.post( new Runnable(){
        public void run(){
            Toast.makeText(context, "Created a server socket",Toast.LENGTH_LONG).show(); 
        }
    });
  }
22
Harshal Voonna

C'est une autre manière qui n'est pas mentionnée ici comme suit:

Étape 1: Définir Gestionnaire en tant que global

Handler handler;

Étape 2: Initialise le gestionnaire dans doInBackground () méthode comme suit:

@Override
protected Void doInBackground(Void... params) {
    Handler handler = new Handler() {
    @Override
    public void handleMessage(Message msg) {
        if (msg.what == 1) {
           //your code
        }
    }
  };
}

Étape 3: Et maintenant, vous pouvez appeler ce gestionnaire n'importe où dans le code en appelant

if(handler != null){
  handler.sendEmptyMessage(1);
}

Ce que vous pouvez faire de plus, c'est que vous pouvez envoyer des données via le gestionnaire comme suit:

Message message = new Message();
Bundle bundle = new Bundle();
bundle.putInt("KEY", value);
message.setData(bundle);
handler.sendMessage(message);

Et gérer les données dans votre gestionnaire comme ci-dessous

handler = new Handler(){ 
    @Override
    public void handleMessage(Message message) {
        Bundle bundle = message.getData();
        Integer value = bundle.getInt("KEY");

    }
};
4
Pankaj

affichez votre pain grillé dans onPostExecute ou onPreExecute. doInBackGround s'exécute sur un thread séparé, mais les deux autres méthodes s'exécutent sur le thread d'interface utilisateur.

Mais s'il est indispensable de montrer le pain grillé dans doInBackGround, vous pouvez utiliser Handler.post ou runonUiThread pour afficher le pain grillé.

2
stinepike

Vous ne pouvez pas afficher Toast dans un fil non-UI (c'est-à-dire faire en arrière-plan) .Vous pouvez essayer le concept du drapeau.

public class HttpRequest extends AsyncTask<String[], Void, String> {
    boolean flag=false;
....
...
....
 @Override
    protected String doInBackground(String[]... params) {
   //set flag as true when you need to trigger the Toast
 try{
   //Some Network Calls
     } catch (HttpHostConnectException e) {
    flag=true;   
  //Triggered Flas when i got Exceptions          
       }
}
 @Override
    protected void onPostExecute(String result) {
        if(flag){
            Toast.makeText(activity, "HttpHostConnectException Occured ", Toast.LENGTH_SHORT).show();
        }


}

Happy Coding .. !!! entrez le code ici

2

nous pouvons le faire en passant une interface à la classe AsyncTask et en effectuant un rappel dans onPostExecute method. 

public interface IResult {
    void onSuccess(String result);
    void onError(String error);                                                  
}

public static class AsyncTaskClass extends AsyncTask<String, String, Boolean> {

    IResult iResult;

    AsyncTaskClass(IResult iResult){
        this.iResult = iResult;
    }

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
    }

    @Override
    protected Boolean doInBackground(String... params) {
        boolean result;
        try {
            //doing BackGround Operation Here
            result = true;

        } catch (Exception e) {
            Log.e(TAG,"Error: " + e.getMessage());
            result = false;
        }

       return result;
    }

    @Override
    protected void onPostExecute(Boolean success) {
        super.onPostExecute(success);
        Log.w(TAG, "On Post Execute: " + success);
        if(success)
            iResult.onSuccess("AsyncTask done successfully.");
        else
            iResult.onSuccess("Sorry! something went wrong.");

    }
}                                                                      
  IResult iResult = new IResult() {
      @Override
      public void onSuccess(String result) {
          Toast.makeText(PostActivity.this, result, Toast.LENGTH_LONG).show();
      }

      @Override
      public void onError(String error) {
          Toast.makeText(PostActivity.this, error, Toast.LENGTH_LONG).show();
      }
  };
  String param1 = "some value 1";
  String param2 = "some value 2";

  new AsyncTaskClass(iResult).execute(param1, param2);`
0
ImFarhad

Vous essayez d'afficher du pain grillé dans un fil non-ui, c'est pourquoi cette erreur apparaît.

Si vous souhaitez afficher toast dans la méthode doInBackground, vous devez écrire votre logique Toast dans le fil de l'interface utilisateur.

jetez un oeil à ci-dessous le lien de réponse https://stackoverflow.com/a/11797945/582571

Mais il n'est pas conseillé d'avoir une manipulation de l'interface utilisateur sous un thread non-ui

0
rajpara