Intereting Posts

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 (некоторый идентификатор), поэтому я должен вызвать эти задачи в строке. В api уровне 10 это возможно?

Заранее спасибо!

Br, Peter

Solutions Collecting From Web of "Android-вызов AsyncTask сразу после завершения"

Вы можете использовать getStatus() проверяет, AsyncTask ли команда 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 } } }); 

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

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

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

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

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

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