web-dev-qa-db-ja.com

AsyncTask.get()が呼び出されたときにProgressDialogが表示されない

重複の可能性:
AsyncTaskはUIの脅威をブロックし、プログレスバーを遅延で表示します

任意のサーバーからJSONを取得しているときにprogressDialogを表示したいと思います。そのため、私はソリューションとしてAsyncTaskを使用していました(別の方法はわかりません)。

AsyncTaskインスタンスを使用して.get()メソッドを呼び出すまで、ProgressDialogは正常に機能します。どういうわけかUIをブロックしていると思います。これが私のAsyncTaskです:

public class myAsync extends AsyncTask<String, String, List> {

    String message; // for dialog message
    ProgressDialog progress; 
    Intent myIntent;
    Context ctx;

    public myAsync(String message, Context ctx) {
        this.message = message;
        this.ctx = ctx;
        progress = new ProgressDialog(ctx);
    }

    @Override
    protected void onPreExecute() { 
        progress.setMessage(message);
        progress.setIndeterminate(true);
        progress.setCancelable(false);
        progress.show();    
    }

    @Override
    protected List doInBackground(String... params) {
        //returns any list after the task
        return anyList; 
    }

    @Override
    protected void onPostExecute(List result) {
        if(progress.isShowing())
            progress.dismiss();
    }
}

そして、これがAsyncTaskを呼び出すmyActivityです。

myAsync asyncTask = new myAsync("Loading...", this);
asyncTask.execute("Any string", "Other string");
asyncTask.get(); // If I comment out this line, ProgressDialog works

実行後、doInBackgroundとonPostExecuteの両方の結果をログに記録しようとしても、問題はありません。しかし、.get()を使用して取得したい場合、結果のProgressDialogは表示されないか、表示される時間が非常に短い(おそらく0.2秒)

どうしたの?

17
Ogulcan Orhan

はい、get()waits必要に応じて計算が完了し、その結果を取得します。これは、UIスレッドをブロックし、結果を待っていることを意味します。

解決策:getを呼び出さないでください

通常、postExecuteで関数(コールバック)を呼び出します。

26
rds

.get() を呼び出すと、現在のスレッド(UIスレッド)が待機するため、AsyncTaskが有効な「SyncTask」に変更されます。 AsyncTaskが処理を完了するまで。 UIスレッドをブロックしているため、ProgressDialog.show()メソッドの呼び出しでは、ダイアログがそれ自体に画面を描画できるようにする機会はありません。

呼び出しを削除すると、バックグラウンドで正しく実行できるようになります。

タスクの完了後に処理を行う必要がある場合は、タスクをonPostExecuteメソッド自体に配置するか、ActivityからonPostExecuteへのコールバックを使用することをお勧めします。

16
Jake Wharton

私があなたの質問を正しく理解している場合は、ProgressDialogでAsyncTaskの進行状況を更新する必要がありますが、これは現在機能していません。したがって、注意すべき点がいくつかあります。.get()で何を達成しようとしているのかわかりませんが、進行状況を表示したいと思います。

以下のプログラムを変更して、AsyncTaskの進行状況に合わせてUIスレッドを更新しました。 pdate進行状況が必要になるたびに、progメソッドでそのdoInBackground変数を更新します。

public class myAsync extends AsyncTask<String, Integer, List> {

  String message; // for dialog message
  ProgressDialog progress; 
  Intent myIntent;
  Context ctx;

  public myAsync(String message, Context ctx) {
    this.message = message;
    this.ctx = ctx;
    progress = new ProgressDialog(ctx);
  }

  @Override
  protected void onPreExecute() { 
    // Runs on the UI thread
    progress.setMessage(message);
    progress.setIndeterminate(true);
    progress.setCancelable(false);
    progress.show();    
  }

  @Override
  protected List doInBackground(String... params) {
    // Runs in the background thread
    // publish your progress here!!
    int prog = 5; // This number will represent your "progress"
    publishProgress(prog);
    return anyList; 
  }


  protected void onProgressUpdate(Integer... progress) {
    // Runs in the UI thread
    // This method will fire (on the UI thread) EVERYTIME publishProgress
    // is called.
    Log.d(TAG, "Progress is: " +progress);
  }

  @Override
  protected void onPostExecute(List result) {
    // Runs in the UI thread

    for (int i=0; i<result.size(); i++) {
      Log.d(TAG, "List item: " + result.get(i));
    }

    if(progress.isShowing())
      progress.dismiss();
  }
}
4
Marvin Pinto