30

Android AsyncTask に問題があります。TextView ボタンと画像を含む Activity があります。ユーザーがこのアクティビティに入ると、asynctask を開始して、ユーザーがアクティビティから移動できるかどうかを確認します (タスクがボタンを非アクティブにしないまで)。次に、別の非同期タスクを開始して画像を取得します。だから私は内部クラスを作りました:

AsyncTask<String, Void, JSONObject>() authTask = new AsyncTask<String, Void, JSONObject>() {
     @Override
     protected JSONObject doInBackground(String... params) {
         //call the rest api
     }
     @Override
     protected void onPostExecute(JSONObject result) {
         // check the result
         // and make another asynctask
         AsyncTask<String, Void, Bitmap> imageTask = new Async.... {
             // get image
         }
         imageTask.execute();
     }
}

authTask.execute(); UIスレッドから呼び出し ます。

私はこれについて気分が悪く、特にうまくいかないようです (数回は問題ありませんが、突然「フリーズ」します: ハングするだけでプログレス バーが回転する例外はありません。何も起こらず、ボタンはアクティブになりません。)情報を取得する別の方法があり、それが終了したらすぐに別のタスクを開始しますか?

UDPATE: 私は API レベル 10 で作業しています。APIレベル10では可能ですか?

前もって感謝します!

ブラ、ピーター

4

7 に答える 7

27

getStatus()が保留中、実行中、または終了しているかどうかのチェックを使用できますAsyncTask。また、完了したら、新しいタスクを開始します。次のように:

if(authTask .getStatus() == AsyncTask.Status.PENDING){
    // My AsyncTask has not started yet
}

if(authTask .getStatus() == AsyncTask.Status.RUNNING){
    // My AsyncTask is currently doing work in doInBackground()
}

if(authTask .getStatus() == AsyncTask.Status.FINISHED){
    // START NEW TASK HERE
}

アプリの例:

btn.setOnClickListener(new View.OnClickListener()
  {
    public void onClick(View v)
      {
        if (authTask != null && authTask.getStatus() == AsyncTask.Status.FINISHED) {
           //START YOUR NEW TASK HERE
        }
        else
        {
          //IGNORE BUTTON CLICK
        }
      }
   }); 
于 2012-04-06T20:48:57.243 に答える
22

1:

authTask のコードと imageTask のコードを、1 つのdoInBackground(). この単一の AsyncTask インスタンスは、単一のexecute()ステートメントによって起動されます。これは、必要な UI インタラクションに応じて、実用的である場合とそうでない場合があります。


2:

編集: kabuku が指摘したように、この情報は主に HoneyComb+ に関するものです。ハニカム以前は、間違いなく上記のオプション1を使用します。executeOnExecutor()は API レベル 11以降です

最近のバージョンでexecute()は、デフォルトで AsyncTasks を連続して送信します (ICS+)。これを確実に実行したい場合は、シリアル エグゼキューターを指定します。

あなたの場合、これは次のようになります。

authTask.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR);
// Image task will only be done AFTER textViewTask is done
imageTask.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR);

新しいバージョンの場合、単純な

...
// ICS+ and pre honeycomb (I think)
authTask.execute();
// Image task will only be done AFTER textViewTask is done
imageTask.execute();
...

AsycnTask.execute() ドキュメントから:

注: この関数は、プラットフォームのバージョンに応じて、単一のバックグラウンド スレッドまたはスレッドのプールのキューにタスクをスケジュールします。最初に導入されたとき、AsyncTasks は単一のバックグラウンド スレッドでシリアルに実行されました。DONUT 以降、これはスレッドのプールに変更され、複数のタスクが並行して動作できるようになりました。HONEYCOMB の後、並列実行によって引き起こされる一般的なアプリケーション エラーを回避するために、これをシングル スレッドに戻す予定です。


PS: 互いに独立してタスクを実行するには、AsyncTask.THREAD_POOL_EXECUTOR. それには別のエグゼキュータが必要です:

// Go parallel! (NOT what you want)
task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
于 2012-04-06T21:05:32.480 に答える
5

AsyncTask をネストするのは適切な設計ではありません。doInBackgroundですべての面倒な作業を行い、結果を投稿/更新するだけです。つまり、最初の AsyncTask に 2 番目の AsyncTask の処理を​​組み合わせます。

于 2012-04-06T20:41:42.873 に答える
1
int count;

 private void attemptConnect() 
 {
   count = 0;
   str_lang = "English";
   str_wait = "Plaese Wait";

   new AllQuestion().execute();

}


private class AllQuestion extends AsyncTask<String, String, String> {
    ProgressDialog pg;

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

        pg = new ProgressDialog(LanguageActivity.this);
        pg.setProgressStyle(ProgressDialog.STYLE_SPINNER);
        pg.setMessage(str_wait);
        pg.setCancelable(false);
        pg.show();
    }

    @Override
    protected String doInBackground(String... strings) {
        try {
            SoapObject soapObject = new SoapObject(AppConstant.NAMESPACE, AppConstant.QUESTION_SOAP_METHOD); 
            soapObject.addProperty("language", str_lang);

            SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
            envelope.dotNet = true;
            envelope.setOutputSoapObject(soapObject);

            HttpTransportSE se = new HttpTransportSE(AppConstant.webUrl);
            se.call(AppConstant.QUESTION_SOAP_ACTION, envelope);


            Object responce = envelope.getResponse();
            Log.d("Question List:=>>", "" + responce);

            return responce.toString();
        } catch (Exception e) {
            e.printStackTrace();
            pg.dismiss();
            return null;
        }
    }

    @Override
    protected void onPostExecute(String s) {
        super.onPostExecute(s);

        if (pg.isShowing()) {
            pg.dismiss();
            Log.i(TAG, s);

            if (s != null || !s.equalsIgnoreCase("")) {
                try {
                    JSONArray array = new JSONArray(s);

                    for (int i = 0; i < array.length(); i++) {
                        JSONObject obj = array.getJSONObject(i);

                        String queId = obj.getString(TAG_QID);
                        String que = obj.getString(TAG_QUE);
                        String str_Opt = obj.getString(TAG_OPT);

                        question = new Question(queId, que, str_lang, str_catId, str_Opt, manager.getDateTime());
                        helper.insertQuestion(question);
                    }
                    count++;
                    if (count < 5) {
                        if (count == 1) {
                            str_lang = "German";
                            str_wait = "bitte warte einen Moment";

                                new AllQuestion().execute();
                        }
                        if (count == 2) {
                            str_lang = "Italian";
                            str_wait = "per favore aspetta un momento";

                                new AllQuestion().execute();
                        }
                        if (count == 3) {
                            str_lang = "Chinese";
                            str_wait = "请稍候";

                                new AllQuestion().execute();
                        }
                        if (count == 4) {
                            str_lang = "French";
                            str_wait = "patientez s'il-vous-plait";

                                new AllQuestion().execute();

                    }
                    Log.d("All Question:-", question.toString());

                } catch (JSONException e) {
                    e.printStackTrace();
                }
            }
        }
    }

}
于 2016-10-06T12:55:45.213 に答える
1

あなたが示したコードから、2番目のタスクを生成するのは意味がないようです。doInBackground承認直後の最初のタスク内でイメージを取得するだけです。間に UI を更新する必要がある場合は、進行中の更新で行うことができます。

于 2012-04-06T20:42:56.580 に答える
0

1 つの非同期タスクで非同期シリーズを作成するというアイデアがあります。

protected Boolean doInBackground(String... params) {
            if(params[0] == "taskA") {
              //do somthing
              params[0] = "taskB";
            }
            if(params[0] == "taskB") {
              //do somthing
              params[0] = "taskC";
            }
            if(params[0] == "taskC") {
              //do somthing
              params[0] = "taskD";
            }
            if(params[0] == "taskD") {
              //do somthing
              return true;
            }

メインスレッドでは、次のように async タスクを呼び出すだけです。

ShowMyProgress(); //if you like
new MyAsyncTask().execute("taskA");

最後に、次のように onPostExecute で進行状況を非表示にすることができます。

protected void onPostExecute(final Boolean success) {
        if (success) {
            ....

            HideMyProgress();
        }
}
于 2016-08-27T04:59:49.927 に答える