2012-04-03 5 views
37

У меня есть функция, AppHelper.isOnline(Context context), я вызываю в разных частях моего приложения, чтобы проверить, что сеанс не был таймаутом, прежде чем делать запрос HTTP.Android wait AsyncTask для завершения

public void onClick(View v) { 
     Intent intent = null; 
     switch (v.getId()) { 

     case R.id.buttonPagamenti: 
      if (AppHelper.isOnline(this)) 
      { 
       //here AppHelper.isOnline should have finished it's async task 
       intent = new Intent(this, OrdineCreaActivity.class); 
       this.startActivityForResult(intent, R.id.buttonPagamenti); 
      } 
      break; 
... 

Внутри AppHelper.isOnline(), я уверен, выполнение в AsyncTask, что входит в систему, таким образом делая сетевой запрос, который не может быть запущен на пользовательском интерфейсе, потому что в противном случае я получаю исключение. Мне нужно дождаться, когда он закончит ПЕРЕД продолжением кода внутри if. Как я могу это сделать ?

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

ответ

81

У вас есть два варианта:

Либо используйте метод AsyncTask «s get(long timeout, TimeUnit unit) как то:

task.get(1000, TimeUnit.MILLISECONDS); 

Это сделает ваш основной поток должен ожидать результата AsyncTask в большинстве 1000 миллисекунд (как за комментарий @ user1028741: на самом деле существует также бесконечно ожидающий метод - AsyncTask#get(), который также может работать для вас в некоторых случаях).

В качестве альтернативы вы можете отобразить диалоговое окно прогресса в задаче async, пока оно не закончится. См. Это thread (Мне не нужно копировать код). В основном отображается диалоговое окно прогресса, когда задача async выполняется и скрывается, когда она заканчивается.

У вас есть еще третий вариант:»если Thread достаточно для ваших потребностей, вы можете просто использовать его метод join Однако, если задача выполняется долгое время, вы все равно должны показать окно выполнения, в противном случае вы получите. исключение из главного потока неактивны слишком долго.

+0

Я пробовал соединение, но проблема заключается в том, что async.exec() не запускается до того, как соединение начнет работать, поэтому приложение будет оставаться неопределенно, tommorow собирается попробовать задачу.get – max4ever

+2

задача async имеет диалог выполнения, но она не останавливает запуск нового действия – max4ever

+1

task.get() - это то, что мне нужно, спасибо !!! – max4ever

1
intent = new Intent(this, OrdineCreaActivity.class); 
context.startActivityForResult(intent, R.id.buttonPagamenti); 

Написать эти строки в onPostExecute() из вас AysncTask. потому что, если мы используем AsyncTask это обыкновение ждать там, пока задача полной.

+0

да, но иногда мне не нужно начинать новую деятельность, может быть, я делаю другие вещи, мне нужно остановить основной поток ui и ждать async – max4ever

+0

Я не получил вас, вы можете быть более конкретным –

+0

в некоторых точках моего приложения мне нужно проверить, если пользователь вошел в систему, и если нет, мне нужно автозарегистрироваться для него, я бы хотел избежать 3000 различных обратных вызовов (для вызова onPostExecute) – max4ever

3

попытаться использовать

if (AppHelper.isOnline(this)) 
     { 
      while(!task.isCancelled()){ 
       // waiting until finished protected String[] doInBackground(Void... params)   
       } 
      intent = new Intent(this, OrdineCreaActivity.class); 
      this.startActivityForResult(intent, R.id.buttonPagamenti); 
     }  

Для получения более подробной информации читайте http://developer.android.com/reference/android/os/AsyncTask.html

+0

и откуда взять переменную задачи? Необходимо изменить isOnline от boolean до AsyncTask? – max4ever

+0

AsyncTask task = new AppHelper(); task.execute(); – Rafiq

+0

AppHelper должен расширять AsyncTask и реализовывать doInBackground (...), onPostExecute (...) и т. Д. Метод. – Rafiq

2

ответ Рафика не работал для меня - приложение зависло. Я думаю, что причина связана с природой isCancelled(): «Возвращает true, если эта задача была отменена, прежде чем она завершится нормально». Если задача завершается нормально (т. Е. Не отменяется), то while(!task.isCancelled()) { } будет циклически навечно.

Чтобы решить эту проблему, создайте булевский флаг, который вы установите на false, а затем переверните на true в task.onPostExecute(). Затем сделайте while(!flag) { } перед переключением. Кроме того, если вы хотите, чтобы дать главный поток «перерыв», чтобы позволить процессу AsyncTask немного быстрее, вы можете сделать это попробовать:

while (!flag) { 
    try { Thread.sleep(100); } 
    catch (InterruptedException e) { e.printStackTrace(); } 
} 

Это, кажется, работает хорошо для меня.

+0

Это именно то, что я пытаюсь сделать, но по какой-то причине метод onPostExecute не вызывается, поэтому пользовательский интерфейс застревает в методе Thread.sleep. – emiliosg

+1

@Emiliosg - Вы уверены, что ваш AsyncTask завершается? Если AsyncTask никогда не завершается, вы никогда не получите «onPostExecute()», и вы будете ждать его ожидания. Попробуйте добавить некоторые logging к вашему 'doInBackground()', чтобы убедиться, что он успешно делает то, что он должен делать. –

+0

Неплохо использовать ожидание ожидания, см. Https://www.facebook.com/arig/posts/10105815276466163 –

Смежные вопросы