web-dev-qa-db-ja.com

トーストをAndroid AsyncTask?

AsyncTask<URL, Integer, Long>で拡張されたinitial_backgroundクラスでToastを表示しようとしています。 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メソッドでトーストを表示したい

18
Nomiluks

バックグラウンドスレッドでUIを更新することはできません。 doInBackground()は、バックグラウンドスレッドで呼び出されます。 UIスレッドでUIを更新する必要があります。

_      runOnUiThread(new Runnable(){

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

onPreExecute()onPostExecute(Result)は、UIスレッドで呼び出されます。ここでトーストを表示できます。

onProgressUpdate(Progress...)は、publishProgress(Progress...)の呼び出し後にUIスレッドで呼び出され、プログレスバーをアニメーション表示したり、テキストフィールドにログを表示したりできます。

doInBackground()計算の結果はonPostExecute(Result)のパラメーターなので、doinBackground()に結果を返し、onPostExecute(Result)にトーストを表示します

@Stine Pikeが提案するハンドラーを使用することもできます

明確にするために、トピックの下のリンクを確認してください:The 4 steps

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

28
Raghunandan

ハンドラーオブジェクトを作成し、それを使用してすべての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(); 
        }
    });
  }
23
Harshal Voonna

これは、次のようにここで言及されていない別の方法です。

ステップ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
Pankaj

onPostExecuteまたはonPreExecuteでトーストを表示します。 doInBackGroundは別のスレッドで実行されますが、他の2つのメソッドはUIスレッドで実行されます。

ただし、doInBackGroundでトーストを表示する必要がある場合は、 Handler.post または runonUiThread を使用してトースト表示を実行できます。

2
stinepike

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


}

Happy Coding .. !!!ここにコードを入力してください

これを行うには、AsyncTaskクラスにインターフェイスを渡し、onPostExecuteメソッドでコールバックを作成します。

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

非UIスレッドでトーストを表示しようとしているため、このエラーが表示されます。

DoInBackgroundメソッドでトーストを表示する場合は、UIスレッド内にトーストロジックを記述する必要があります。

以下の回答リンクをご覧ください https://stackoverflow.com/a/11797945/582571

しかし、非UIスレッドの下でUI操作を行うことはお勧めできません

0
rajpara