Подтвердить что ты не робот

Android-вызов AsyncTask сразу после того, как другой закончен

У меня есть проблема с Android AsyncTask. Существует Activity, в котором есть кнопка TextView a и изображение. Когда пользователь вводил это действие, я запускаю асинтезу, чтобы проверить, может ли пользователь перейти от активности (пока задача не завершит действие кнопки неактивно). Затем я хочу запустить еще один asyntask, чтобы получить изображение. Поэтому я сделал внутренний класс:

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(); из потока пользовательского интерфейса.

У меня плохое настроение по поводу этого, особенно кажется, что это не работает (это нормально несколько раз, но внезапно "замораживается": исключение не висит, а индикатор прогресса вращается. Ничего не происходит, и кнопка не будет активный.) Есть еще один способ получить информацию, и когда она закончится, сразу начнется другая задача?

UDPATE: Я работаю с api level 10. В authTask я получаю некоторую информацию, которая необходима для запуска imageTask (некоторый id), поэтому я должен вызывать эти задачи в строке. В api уровне 10 можно?

Спасибо заранее!

Бр, Питер

4b9b3361

Ответ 1

вы можете использовать getStatus() проверяет, ожидает ли команда AsyncTask, работает или завершена. и когда finsh запустит вашу новую задачу.:

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

Ответ 2

1

Вы можете написать код для authTask, а затем для imageTask, один за другим, в пределах одного doInBackground(). Этот единственный экземпляр AsyncTask был бы огнем одним оператором execute(). Это может быть или не быть практичным в зависимости от необходимых взаимодействий пользовательского интерфейса.


2

Изменить: как отметил kabuku, эта информация в основном предназначена для HoneyComb+. Pre 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);

Ответ 3

Не очень хороший дизайн для гнезда AsyncTask. Сделайте всю тяжелую работу в doInBackground и просто публикуйте/обновите результаты. Другими словами, объедините обработку второй AsyncTask в первой.

Ответ 4

Из кода, который вы показали, кажется, не имеет смысла порождать вторую задачу. Просто получите изображение внутри doInBackground первой задачи сразу после авторизации. Если вам нужно обновить интерфейс между ними, вы можете сделать это в процессе обновления.

Ответ 5

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

}

Ответ 6

У меня есть идея сделать серию async только в одной асинхронной задаче:

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