Konwertuję mój kod z używania Handler
na AsyncTask
. Ten ostatni jest świetny w tym, co robi - asynchronicznych aktualizacjach i obsłudze wyników w głównym wątku interfejsu użytkownika. Nie jest dla mnie jasne, jak radzić sobie z wyjątkami, jeśli coś pójdzie nie tak AsyncTask#doInBackground
.
Sposób, w jaki to robię, to mieć obsługę błędów i wysyłać do niego komunikaty. Działa dobrze, ale czy jest to „właściwe” podejście, czy też jest lepsza alternatywa?
Rozumiem również, że jeśli zdefiniuję obsługę błędu jako pole działania, powinien on zostać wykonany w wątku interfejsu użytkownika. Jednak czasami (bardzo nieprzewidywalnie) otrzymuję wyjątek informujący, że kod wyzwalany z Handler#handleMessage
jest wykonywany w niewłaściwym wątku. Czy Activity#onCreate
zamiast tego powinienem zainicjować procedurę obsługi błędów ? Umieszczanie runOnUiThread
w programie Handler#handleMessage
wydaje się zbędne, ale działa bardzo niezawodnie.
Odpowiedzi:
Trzymam się
Throwable
lubException
wAsyncTask
samej instancji, a następnie coś z nim robięonPostExecute()
, więc moja obsługa błędów ma opcję wyświetlenia okna dialogowego na ekranie.źródło
AsyncTask
następujący wzór, który opisuję.Utwórz obiekt AsyncResult (którego możesz również użyć w innych projektach)
Zwróć ten obiekt z metod AsyncTask doInBackground i sprawdź go w postExecute. (Możesz użyć tej klasy jako klasy bazowej dla innych zadań asynchronicznych)
Poniżej znajduje się makieta zadania, które pobiera odpowiedź JSON z serwera WWW.
źródło
super()
sięAsyncTaskResult
, gdy klasa nic nie przedłużyć?Kiedy czuję potrzebę odpowiedniego obsłużenia wyjątków
AsyncTask
, używam tego jako superklasy:Jak zwykle, nadpisujesz
doInBackground
swoją podklasę, aby wykonać pracę w tle, szczęśliwie rzucając Wyjątki w razie potrzeby. Jesteś wtedy zmuszony do implementacjionPostExecute
(ponieważ jest abstrakcyjny), a to delikatnie przypomina ci o obsłudze wszystkich typówException
, które są przekazywane jako parametry. W większości przypadków Wyjątki prowadzą do pewnego typu wyjścia interfejsu użytkownika, więconPostExecute
jest to idealne miejsce do zrobienia tego.źródło
params
dalej, aby był bardziej podobny do oryginału i łatwiejszy do migracji?new Task("Param").execute()
więcejnew Task().execute("Param")
.Jeśli chcesz używać frameworka RoboGuice, który zapewnia inne korzyści, możesz wypróbować RoboAsyncTask, które ma dodatkowe wywołanie zwrotne onException (). Działa naprawdę dobrze i używam go. http://code.google.com/p/roboguice/wiki/RoboAsyncTask
źródło
RoboGuice
jeszcze żyje? Wygląda na to, że nie był aktualizowany od 2012 roku?Stworzyłem własną podklasę AsyncTask z interfejsem, który definiuje wywołania zwrotne dla sukcesu i niepowodzenia. Więc jeśli wyjątek zostanie zgłoszony w Twoim AsyncTask, funkcja onFailure otrzymuje wyjątek, w przeciwnym razie wywołanie zwrotne onSuccess dostaje przekazany wynik. Dlaczego android nie ma czegoś lepszego, jest poza mną.
źródło
Bardziej kompleksowe rozwiązanie rozwiązania Cagatay Kalan pokazano poniżej:
AsyncTaskResult
ExceptionHandlingAsyncTask
Przykładowe zadanie
źródło
Ta prosta klasa może ci pomóc
źródło
Innym sposobem, który nie zależy od udostępniania zmiennych składowych, jest użycie anulowania.
To pochodzi z dokumentów Androida:
Możesz więc wywołać anulowanie w instrukcji catch i upewnić się, że onPostExcute nigdy nie jest wywoływany, ale zamiast tego onCancelled jest wywoływany w wątku interfejsu użytkownika. Możesz więc wyświetlić komunikat o błędzie.
źródło
cancel(boolean)
w wyniku czego wezwanie doonCancelled()
istniało od początku, aleonCancelled(Result)
zostało dodane w API 11 .Właściwie AsyncTask używa FutureTask & Executor, FutureTask obsługuje łańcuch wyjątków Najpierw zdefiniujmy klasę pomocniczą
Po drugie, użyjmy
źródło
Osobiście skorzystam z tego podejścia. Możesz po prostu złapać wyjątki i wydrukować ślad stosu, jeśli potrzebujesz informacji.
spraw, aby twoje zadanie w tle zwróciło wartość logiczną.
to jest tak:
źródło
Inną możliwością byłoby użycie
Object
jako typu zwracanego ionPostExecute()
sprawdzania typu obiektu. To jest krótkie.źródło
Jeśli znasz poprawny wyjątek, możesz wywołać
na przykład:
i przejdź do „onProgressUpdate” i wykonaj następujące czynności
Będzie to pomocne tylko w niektórych przypadkach. Możesz także zachować
Global
Exception
zmienną i uzyskać dostęp do wyjątku.źródło