2012-04-03 17 views
37

Mam funkcję, AppHelper.isOnline(Context context), wzywam różne części mojej aplikacji, aby sprawdzić, czy sesja nie przekroczyła limitu czasu przed wysłaniem żądania HTTP.Poczekaj na Android AsyncTask, aby zakończyć

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

Wewnątrz AppHelper.isOnline(), jestem wykonujący takie AsyncTask że loguje się, dzięki czemu żądania sieciowe, które nie mogą być uruchamiane na interfejsie użytkownika, ponieważ w przeciwnym razie pojawia się wyjątek. Muszę poczekać, aż się zakończy, ZANIM powrócisz do kodu wewnątrz if. Jak mogę to zrobić ?

Problem to działanie rozpoczyna się jako pierwsze, następnie wykonuje się AsyncTask, więc gdy działanie oczekuje prawidłowej zalogowanej sesji, ulega uszkodzeniu.

Odpowiedz

81

Masz dwie opcje:

użyć metoda AsyncTask „s get(long timeout, TimeUnit unit) tak:

task.get(1000, TimeUnit.MILLISECONDS); 

Uczyni to główne oczekiwania wątek na skutek AsyncTask co najwyżej 1000 milisekund (jak za @ user1028741 comment: w rzeczywistości istnieje również metoda nieskończenie oczekująca - AsyncTask#get(), która może również wykonać pracę dla ciebie w niektórych przypadkach).

Alternatywnie można wyświetlić okno dialogowe postępu w asynchronicznym zadaniu do momentu jego zakończenia. Zobacz to thread (Nie ma potrzeby, abym kopiował poza kod). Zasadniczo wyświetlane jest okno postępu podczas wykonywania zadania asynchronicznego i jest ukrywane po zakończeniu.

Masz nawet trzecią opcję: "jeśli Thread jest wystarczająca dla twoich potrzeb, możesz po prostu użyć jej metody join.Jeśli jednak zadanie trwa długo, nadal musisz wyświetlić okno dialogowe postępu, w przeciwnym razie dostaniesz wyjątek ze względu na głównym wątku będącego nieaktywny przez zbyt długi.

+0

Próbowałem połączyć, ale problem jest async.exec() nie rozpoczyna się przed dołączeniem kopnięć, więc aplikacja trzyma się nieskończenie, jutro będzie spróbuj wykonać zadanie.get – max4ever

+2

zadanie async ma okno dialogowe postępu, ale nie zatrzymuje ono nowej aktywności od uruchomienia – max4ever

+1

task.get() jest właśnie tym, czego potrzebowałem, dzięki !!! – max4ever

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

Napisz powyższe linie w onPostExecute() z was AysncTask. bo jeśli używamy AsyncTask to przyzwyczajenie czekać tam, aż zadanie zakończone.

+0

tak, ale czasami nie muszę zaczynać nowej działalności może robię inne rzeczy, muszę zatrzymać główny wątek i czekać na async – max4ever

+0

Nie udało mi się być bardziej konkretnym –

+0

w niektórych punktach w mojej aplikacji muszę sprawdzić, czy użytkownik jest zalogowany, a jeśli nie muszę go automatycznie zalogować, chciałbym uniknąć 3000 różnych wywołań zwrotnych (dla połączenia onPostExecute) – max4ever

3

spróbuj użyć

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

Aby uzyskać więcej informacji przeczytaj http://developer.android.com/reference/android/os/AsyncTask.html

+0

i gdzie mogę uzyskać zmienną zadania? muszę zmienić isOnline z boolean na AsyncTask? – max4ever

+0

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

+0

AppHelper powinien rozszerzyć AsyncTask i zaimplementować metodę doInBackground (...), onPostExecute (...), itp. – Rafiq

2

odpowiedź Rafika za nie działa dla mnie - aplikacja zawieszony. Myślę, że powód ma związek z naturą isCancelled(): "Zwraca true, jeśli to zadanie zostało anulowane, zanim zostało zakończone normalnie." Jeśli zadanie zakończy się normalnie (tzn. Nie zostanie anulowane), wówczas while(!task.isCancelled()) { } zapętnie się na zawsze.

Aby rozwiązać ten problem, utwórz flagę typu Boolean, którą zainicjujesz pod numerem false, a następnie przerzuć na true w task.onPostExecute(). Następnie wykonaj while(!flag) { } przed przełączeniem działań. Dodatkowo, jeśli chcesz dać główny wątek do „break”, aby pozwolić proces AsyncTask trochę szybciej, można nie spróbować tego:

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

Wydaje się, że dobrze działa na mnie.

+0

To jest dokładnie to, co próbuję zrobić, ale z jakiegoś powodu metoda onPostExecute nie jest wywoływana, więc interfejs zostaje zablokowany w metodzie Thread.sleep. – emiliosg

+1

@Emiliosg - Czy na pewno kończy się AsyncTask? Jeśli AsyncTask nigdy się nie zakończy, nigdy nie dostaniesz 'onPostExecute()' i zawiesisz się na czekaniu. Spróbuj dodać trochę logowania do "doInBackground()", aby upewnić się, że pomyślnie robi to, co powinno. –

+0

Nie jest dobrym pomysłem, aby użyć zajętego oczekiwania, zapoznaj się z https://www.facebook.com/arig/posts/10105815276466163 –

Powiązane problemy