Oczekiwanie na zakończenie pracy zadania asynchronicznego


85

Jestem bardzo nowy w programowaniu i mam pewne wątpliwości.

Mam to, AsyncTaskco nazywam jako RunInBackGround.

i zaczynam ten proces jak:

new RunInBackGround().execute();

Ale chciałbym poczekać, aż to wywołanie zakończy swoje wykonywanie, zanim przejdę do innych instrukcji kodu.

Jak mogę to zrobić?

Czy jest na to sposób?


2
Celem AsyncTask jest to, że jest asynchroniczny, co oznacza, że ​​nie jest zsynchronizowany z resztą kodu.
Gjordis

3
Możesz użyć jego metody onPostExecute () AsyncTask, aby uzyskać wywołanie zwrotne w swojej klasie.
DcodeChef,

5
naprawdę nie chcesz czekać, aż się skończy. Chcesz wiedzieć, kiedy się skończy.
njzk2

3
@DcodeChef jest jedynym, który zrozumiał, czego chce w pytaniu.
Please_Dont_Bully_Me_SO_Lords

1
Myślę, że to jest odpowiedź, której szukasz na stackoverflow.com/questions/13079645/ ...
user3362415

Odpowiedzi:


130

poczekaj, aż to wywołanie zakończy swoje wykonywanie

Będziesz musiał wywołać metodę AsyncTask.get () w celu odzyskania wyniku i zaczekać, aż doInBackgroundwykonanie nie zostanie zakończone. ale spowoduje to zamrożenie głównego wątku interfejsu użytkownika, jeśli nie wywołasz metody get wewnątrz wątku .

Aby uzyskać wynik z powrotem w UI, Rozpocznij wątekAsyncTask jako:

String str_result= new RunInBackGround().execute().get();

3
więc jak czekać na wynik i nie zablokować głównego wątku interfejsu użytkownika ?! powiedz, że kod czeka na wynik, ale w międzyczasie pasek postępu ciągle się toczy!
Muhammad Naderi

2
@MuhammadNaderi: Użyj AsyncTaskbez getmetody iw AsyncTask onPostExecutewywoływana jest metoda, która zapewnia wyniki u w głównym wątku interfejsu użytkownika
ρяσѕρєя K

3
pewnie, że jest to obejście, którego używam już od jakiegoś czasu, ale czasami potrzebuję, aby kod czekał na asynctask, coś awaitw stylu c#, i oczywiście nie blokował głównego wątku
Muhammad Naderi

2
@ ρяσѕρєяK dziękuję, dzięki milionowi. nie masz pojęcia, jak bardzo pociągnąłem za ten problem, ale tylko jeden .get () rozwiązał (żartujesz) tylko jeden .get () !!!!!
Code_Worm

Jak możesz użyć AsyncTask i uniknąć używania get (), aby uniknąć zawieszania się interfejsu użytkownika?
Arjun Issar

36

Chociaż optymalnie byłoby miło, gdyby twój kod mógł działać równolegle, może się zdarzyć, że po prostu używasz wątku, więc nie blokujesz wątku interfejsu użytkownika, nawet jeśli przepływ użycia aplikacji będzie musiał na to czekać.

Masz tutaj prawie 2 opcje;

  1. Możesz wykonać kod, który chcesz czekać, w samym AsyncTask. Jeśli ma to związek z aktualizacją interfejsu użytkownika (wątkiem), możesz użyć metody onPostExecute. Jest to wywoływane automatycznie po zakończeniu pracy w tle.

  2. Jeśli z jakiegoś powodu jesteś zmuszony zrobić to w Aktywności / Fragmentie / Cokolwiek, możesz również po prostu ustawić sobie niestandardowy odbiornik, który nadajesz z AsyncTask. Używając tego, możesz mieć metodę wywołania zwrotnego w swoim działaniu / fragmencie / cokolwiek, co jest wywoływane tylko wtedy, gdy tego chcesz: aka, gdy twoje AsyncTask jest wykonane z tym, na co musiałeś czekać.


6
To świetna odpowiedź, powinna być akceptowana. Tutaj jest również próbka, jak to osiągnąć za pomocą AsyncTasks: stackoverflow.com/questions/12575068/…
Jose Gonzalez

w drugiej opcji, W międzyczasie rzucasz intencję do odbiorcy, główny wątek zostanie wznowiony w prawo. OP tego nie potrzebuje.
LincyTonita,

16

W swojej AsyncTaskdodać jeden ProgressDialog jak:

private final ProgressDialog dialog = new ProgressDialog(YourActivity.this);

Możesz ustawić wiadomość w onPreExecute()metodzie takiej jak:

this.dialog.setMessage("Processing..."); 
this.dialog.show();

iw swojej onPostExecute(Void result)metodzie odrzuć swoje ProgressDialog.


15

AsyncTask ma cztery metody.

onPreExecute  -- for doing something before calling background task in Async

doInBackground  -- operation/Task to do in Background

onProgressUpdate  -- it is for progress Update

onPostExecute  -- this method calls after asyncTask return from doInBackground.

możesz zadzwonić do swojej pracy na onPostExecute()to dzwoni po powrocie zdoInBackground()

OnPostExecute jest tym, co musisz zaimplementować.


1

Myślę, że najłatwiejszym sposobem jest stworzenie interfejsu do pobierania danych z onpostexecute i uruchamiania interfejsu użytkownika z interfejsu:

Utwórz interfejs:

public interface AsyncResponse {
    void processFinish(String output);
}

Następnie w asynctask

@Override
protected void onPostExecute(String data) {
    delegate.processFinish(data);
}

Następnie w twojej głównej działalności

@Override
public void processFinish(String data) {
     // do things

}
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.