Android AsyncTask dla długotrwałych operacji

Cytując dokumentację AsyncTask znalezioną tutaj , pisze

Asynchroniczne zadania powinny być idealnie używane do krótkich operacji (najwyżej kilku sekund.) Jeśli chcesz, aby wątki działały przez długi czas, zaleca się korzystanie z różnych interfejsów API dostarczanych przez Javę.util.współbieżne pacakge, takie jak Executor, ThreadPoolExecutor i FutureTask.

Teraz pojawia się moje pytanie dlaczego ? Funkcja doInBackground uruchamia się poza wątkiem interfejsu użytkownika. Więc co możemy zrobić, mając tu długą działalność ?

Author: user1730789, 2012-10-09

4 answers

Jest to bardzo dobre pytanie, potrzeba czasu jako programista Androida, aby w pełni zrozumieć problem. Rzeczywiście AsyncTask mają dwa główne problemy, które są ze sobą powiązane:

    Są słabo związane z cyklem życia aktywności]} Bardzo łatwo tworzą wycieki pamięci.

Wewnątrz RoboSpice Aplikacja motywacyjna ( dostępna w Google Play) odpowiadamy na to pytanie szczegółowo. Pozwoli to na dogłębny wgląd w asynchroniczne zadania, Ładowarki, ich funkcje i wady a także wprowadzenie do alternatywnego rozwiązania dla żądań sieciowych: RoboSpice. Żądania sieciowe są powszechnym wymogiem w Androidzie i z natury są długotrwałymi operacjami . Oto fragment aplikacji:

Cykl życia Asynktasku i aktywności

Asynchroniczne zadania nie podążają za cyklem życia instancji aktywności. Jeśli uruchomisz Asynktask wewnątrz aktywności i obrócisz urządzenie, aktywność zostanie zniszczona i zostanie utworzona nowa instancja. Ale AsyncTask będzie nie umieraj. Będzie żył, dopóki się nie skończy.

A po jego zakończeniu, AsyncTask nie zaktualizuje interfejsu nowej aktywności. Faktycznie aktualizuje poprzednią instancję czynności, która nie jest już wyświetlany. Może to prowadzić do wyjątku typu java.lang.IllegalArgumentException: Widok Nie dołączony do menedżera okien, jeśli użyj na przykład findViewById, aby odzyskać widok wewnątrz aktywności.

Problem z wyciekiem pamięci

Bardzo wygodne jest tworzenie Asynchroniczne zadania jako wewnętrzne klasy Twoich działań. AsyncTask będzie musiał manipulować widokami aktywności, gdy zadanie jest ukończone lub w toku, korzystanie z wewnętrznej klasy aktywności wydaje się wygodne : wewnętrzne klasy mogą dostęp bezpośrednio do dowolnego pola klasy zewnętrznej.

niemniej jednak, oznacza to, że Klasa wewnętrzna będzie posiadać niewidoczne odniesienie na zewnętrznej instancji klasy: Activity .

Na dłuższą metę powoduje to wyciek pamięci: jeśli AsyncTask trwa długo, utrzymuje aktywność " żywą" podczas gdy Android chciałby się go pozbyć, ponieważ nie może być już wyświetlany. Działalności nie można zbierać śmieci, a to Centralne mechanizm dla Androida do zachowania zasobów na urządzeniu.


To naprawdę bardzo zły pomysł, aby używać asynchronicznych zadań do długotrwałych operacji. Niemniej jednak, są one w porządku dla krótkich żywych, takich jak aktualizowanie widoku po 1 lub 2 sekundach.

Zachęcam do pobrania RoboSpice Motivations app , to naprawdę wyjaśnia to dogłębnie i dostarcza próbek i demonstracji różnych sposobów wykonywania niektórych operacji w tle.

 111
Author: Snicolas,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-02-01 02:52:48
Dlaczego ?

Ponieważ AsyncTask domyślnie używa puli wątków , której nie stworzyłeś . Nigdy nie wiązaj zasobów z puli, której nie stworzyłeś, ponieważ nie wiesz, jakie są wymagania tej puli. I nigdy nie łącz zasobów z puli, której nie utworzyłeś, jeśli dokumentacja dla tej puli nakazuje ci tego nie robić, jak ma to miejsce w tym przypadku.

W szczególności, począwszy od Androida 3.2, Pula wątków używana przez AsyncTask domyślnie (dla aplikacji z android:targetSdkVersion ustawioną na 13 lub higher) ma tylko JEDEN wątek w nim -- jeśli związać ten wątek na czas nieokreślony, żadne z twoich innych zadań nie będzie działać.

 36
Author: CommonsWare,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-10-09 11:00:15

Zadania Aysnc są wyspecjalizowanymi wątkami, które nadal mają być używane z interfejsem graficznym aplikacji, ale przy zachowaniu ciężkich zadań w wątku interfejsu użytkownika. Więc gdy rzeczy takie jak aktualizowanie list, zmiana widoków itp wymagają wykonania pewnych operacji pobierania lub aktualizacji, należy użyć zadań asynchronicznych, aby można było zachować te operacje poza wątkiem interfejsu, ale należy pamiętać, że te operacje są nadal połączone z interfejsem jakoś.

W przypadku dłuższych zadań, które nie wymagają aktualizacji UI, możesz mogą korzystać z usług, ponieważ mogą żyć nawet bez interfejsu użytkownika.

Więc w krótkich zadaniach, użyj zadań asynchronicznych, ponieważ mogą one zostać zabite przez system operacyjny po tym, jak twoja aktywność spawalnicza umrze (zwykle nie umrze w połowie operacji, ale zakończy swoje zadanie). A w przypadku długich i powtarzalnych zadań skorzystaj z usług.

Aby uzyskać więcej informacji, zobacz wątki:

AsyncTask na dłużej niż kilka sekund?

I

AsyncTask nie zatrzyma się nawet wtedy, gdy aktywność ma zniszczone

 3
Author: Anup Cowkur,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:17:54

Problem z AsyncTask polega na tym, że jeśli jest zdefiniowana jako niestatyczna Klasa wewnętrzna aktywności, będzie miała odniesienie do aktywności. W scenariuszu, w którym activity kontener zadania asynchronicznego zakończy się, ale praca w tle w Asynctasku będzie kontynuowana, obiekt activity nie będzie zbierany jako odniesienie do niego, co spowoduje wyciek pamięci.

Rozwiązaniem aby to naprawić jest zdefiniowanie asynchronicznego zadania jako statycznej wewnętrznej klasy aktywności i użycie słabego odniesienia do kontekst.

Ale nadal dobrym pomysłem jest użycie go do prostych i szybkich zadań w tle. Aby stworzyć aplikację z czystym kodem, lepiej jest użyć RxJava do uruchamiania złożonych zadań w tle i aktualizowania interfejsu użytkownika z wynikami z niego.

 0
Author: Arnav Rao,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-28 07:46:20