Как отобразить Toast в Android AsyncTask?

Я пытаюсь отобразить Toast в моем классе initial_background, расширенном с помощью AsyncTask<URL, Integer, Long>. Я получаю эту ошибку в 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();
    }
}
}


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

Вышеприведенный код показывает всю историю. На самом деле, я хочу показать тост в методе doInBackground

Ответы

Ответ 1

Вы не можете обновить ui в фоновом потоке. doonBAckground вызывается в фоновом потоке. Вы должны обновить ui в потоке ui.

      runOnUiThread(new Runnable(){

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

onPreExecute(), onPostExecute (Result), вызывается в потоке ui. Таким образом, вы можете отображать тосты здесь.

onProgressUpdate (Прогресс...), вызывается в потоке пользовательского интерфейса после вызова publishProgress (Прогресс...). может использоваться для анимации индикатора выполнения или отображения журналов в текстовом поле.

Результат вычисления doInbackground() является параметром onPostExecute (Result), поэтому возвращаем результат в doinBackground() и показываем ваш тост в onPostExecute (результат)

Вы также можете использовать обработчик, предложенный @Stine Pike

Для ясности проверьте ссылку ниже в разделе "4 шага".

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

Ответ 2

Создайте объект-обработчик и выполните все ваши сообщения Toast, используя это.

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

Ответ 3

Это другой способ, который не упоминается здесь следующим образом:

Шаг 1: Определите Обработчик как глобальный

Handler handler;

Шаг 2: Обработчик инициализации в doInBackground() следующим образом:

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

Шаг 3: И теперь вы можете вызвать этот обработчик где угодно в коде, вызвав

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

Что еще вы можете сделать, так это отправить данные через обработчик следующим образом:

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

И обрабатывайте данные в вашем обработчике ниже

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

    }
};

Ответ 4

покажите ваш Toast в onPostExecute или onPreExecute. doInBackGround работает в отдельном потоке, но два других метода запускаются в потоке пользовательского интерфейса.

Но если вам нужно показать тост в doInBackGround, вы можете использовать Handler.post или runonUiThread для показа тостов.

Ответ 5

Вы не можете отображать Toast в потоке non-ui (т.е. делать в фоновом режиме). Вы можете попробовать концепцию флага.

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


}

Счастливое кодирование..!!! введите код здесь

Ответ 6

Вы пытаетесь отобразить тост в потоке, отличном от ui, который вызывает эту ошибку.

Если вы хотите отображать тост в методе doInBackground, тогда вы должны написать свою логику Toast внутри потока пользовательского интерфейса.

см. ниже ссылку ответа fooobar.com/info/216995/...

Но не рекомендуется иметь манипуляцию с пользовательским интерфейсом под потоком не-ui