2017-04-14 13 views
11

Chodzi o POST-plaster miodu (czyli Android 3.0+) i poniżej pochodzą z https://developer.android.com/reference/android/app/Activity.htmlzasoby kin w OnPause zamiast onDestroy

Zgodnie z cyklem cytaty, OnStop i onDestroy są usuwalne, to znaczy:

Uwaga „usuwalne” kolumna w tabeli powyżej - w tych metodach , które są oznaczone jako usuwalne, po czym sposób wraca program obsługujący czynności mogą być zabite przez system w każdej chwili, bez inna linia kodu b eing wykonany

  1. Innymi słowy, OnStop (wraz z innymi, które miały miejsce przed tym wydarzeniem) jest gwarantowana się nazywa, ale w tej chwili nie powróci metoda, proces może umrzeć, więc onDestroy jest nie gwarantowane nazywać.

    Kolejne stany Cytat:

    Dla tych metod, które nie są oznaczone jako usuwalne, proces w Activity nie zostanie zabity przez system począwszy od chwili metoda nazywa i kontynuując po powraca .

    Obserwowani przez

    Zatem aktywność jest w stanie usuwalne, na przykład pomiędzy od OnPause() na początku onResume().

  2. Ale to nie robi odpowiada temu, co zostało powiedziane powyżej, chyba odpowiada tylko do PRE-plastra miodu. To nie jest prawda dla POST-plaster miodu, prawda? Zasadniczo, zarówno onPauza, jak i onStop są gwarantowane.

  3. Zakładając, że udostępniam tylko zasoby w onDestroy, może to prowadzić do możliwego wycieku, ponieważ onDestroy może nie zostać wywołany, prawda?

  4. Czy jednak ten scenariusz (np. OnDestroy nie jest nazywany) występuje oprócz, gdy proces zostanie zabity przez sam Android? Czy są jakieś inne scenariusze, które powodują, że nie można nazwać "Przeszkody", , w ten sposób wycieku zasobów.

  5. Czy to prawda, że ​​gdy Android zabija proces, że środki zostaną zniszczone i nie przeciek może wystąpić (nawet jeśli nie jawnie zwolniony zasób?).

Proszę podać szczegółowe informacje czy oświadczenia te (1) (2) (3) (4) (5) są poprawne, czy nie.

+1

"Zasadniczo, zarówno onPause, jak i onStop mają gwarancję nazywania się" - AFAIK, tak. "to prowadzi do możliwego wycieku, prawda?" -- prawdopodobnie nie. 'onDestroy()' zostanie wywołany, chyba że masz nieobsługiwany wyjątek lub proces zostanie zakończony. – CommonsWare

Odpowiedz

15

Po pierwsze, zrozummy, co się dzieje z dokumentacją, którą zacytowałeś.

następujących poleceń pokazać git blame wyjście Activity.java plik w AOSP:

$ cd $AOSP/frameworks/base 
$ git blame ./core/java/android/app/Activity.java 

Istotna część wyjścia:

9066cfe98 (The Android Open Source Project 2009-03-03 19:31:44 -0800 363) * <p>Note the "Killable" column in the above table -- for those methods that 
9066cfe98 (The Android Open Source Project 2009-03-03 19:31:44 -0800 364) * are marked as being killable, after that method returns the process hosting the 
9066cfe98 (The Android Open Source Project 2009-03-03 19:31:44 -0800 365) * activity may killed by the system <em>at any time</em> without another line 
9066cfe98 (The Android Open Source Project 2009-03-03 19:31:44 -0800 366) * of its code being executed. Because of this, you should use the 
9066cfe98 (The Android Open Source Project 2009-03-03 19:31:44 -0800 367) * {@link #onPause} method to write any persistent data (such as user edits) 
9066cfe98 (The Android Open Source Project 2009-03-03 19:31:44 -0800 368) * to storage. In addition, the method 
9066cfe98 (The Android Open Source Project 2009-03-03 19:31:44 -0800 369) * {@link #onSaveInstanceState(Bundle)} is called before placing the activity 
9066cfe98 (The Android Open Source Project 2009-03-03 19:31:44 -0800 370) * in such a background state, allowing you to save away any dynamic instance 
9066cfe98 (The Android Open Source Project 2009-03-03 19:31:44 -0800 371) * state in your activity into the given Bundle, to be later received in 
550116576 (RoboErik      2014-07-09 15:05:53 -0700 372) * {@link #onCreate} if the activity needs to be re-created. 
9066cfe98 (The Android Open Source Project 2009-03-03 19:31:44 -0800 373) * See the <a href="#ProcessLifecycle">Process Lifecycle</a> 
9066cfe98 (The Android Open Source Project 2009-03-03 19:31:44 -0800 374) * section for more information on how the lifecycle of a process is tied 
9066cfe98 (The Android Open Source Project 2009-03-03 19:31:44 -0800 375) * to the activities it is hosting. Note that it is important to save 
9066cfe98 (The Android Open Source Project 2009-03-03 19:31:44 -0800 376) * persistent data in {@link #onPause} instead of {@link #onSaveInstanceState} 
5c40f3fcc (Daisuke Miyakawa    2011-02-15 13:24:36 -0800 377) * because the latter is not part of the lifecycle callbacks, so will not 
9066cfe98 (The Android Open Source Project 2009-03-03 19:31:44 -0800 378) * be called in every situation as described in its documentation.</p> 
9066cfe98 (The Android Open Source Project 2009-03-03 19:31:44 -0800 379) * 
0aae2d4e0 (Dianne Hackborn     2010-12-07 23:51:29 -0800 380) * <p class="note">Be aware that these semantics will change slightly between 
0aae2d4e0 (Dianne Hackborn     2010-12-07 23:51:29 -0800 381) * applications targeting platforms starting with {@link android.os.Build.VERSION_CODES#HONEYCOMB} 
0aae2d4e0 (Dianne Hackborn     2010-12-07 23:51:29 -0800 382) * vs. those targeting prior platforms. Starting with Honeycomb, an application 
0aae2d4e0 (Dianne Hackborn     2010-12-07 23:51:29 -0800 383) * is not in the killable state until its {@link #onStop} has returned. This 
0aae2d4e0 (Dianne Hackborn     2010-12-07 23:51:29 -0800 384) * impacts when {@link #onSaveInstanceState(Bundle)} may be called (it may be 
0aae2d4e0 (Dianne Hackborn     2010-12-07 23:51:29 -0800 385) * safely called after {@link #onPause()} and allows and application to safely 
0aae2d4e0 (Dianne Hackborn     2010-12-07 23:51:29 -0800 386) * wait until {@link #onStop()} to save persistent state.</p> 
0aae2d4e0 (Dianne Hackborn     2010-12-07 23:51:29 -0800 387) * 
9066cfe98 (The Android Open Source Project 2009-03-03 19:31:44 -0800 388) * <p>For those methods that are not marked as being killable, the activity's 
9066cfe98 (The Android Open Source Project 2009-03-03 19:31:44 -0800 389) * process will not be killed by the system starting from the time the method 
9066cfe98 (The Android Open Source Project 2009-03-03 19:31:44 -0800 390) * is called and continuing after it returns. Thus an activity is in the killable 
9066cfe98 (The Android Open Source Project 2009-03-03 19:31:44 -0800 391) * state, for example, between after <code>onPause()</code> to the start of 
9066cfe98 (The Android Open Source Project 2009-03-03 19:31:44 -0800 392) * <code>onResume()</code>.</p> 

Uwaga że ustęp, który omawia poczta-Honeycomb zachowania została dodana przez Dianne Hackborn z dnia 2010-12-07, podczas gdy załączone akapity pochodzą z 2009-03-03.

To, co nam mówi, to że Dianne dodała nowy akapit bez aktualizacji reszty javadoc, a więc sprzeczności. Niestety nie jest to rzadkością w systemie Android.

na pytania:

1) na post-Honeycomb wersjach Androida zarówno onResume() i onStop() są gwarantowane nazywać (jak stwierdził Dianne Hackborn w niej oprócz javadoc Działania związane za).

2) Na wstępnym Honeycomb jest gwarantowana tylko onPause() nazywać (jak stwierdził wcześniejszej wersji javadoc Działania związane'S)

3,4,5) onDestroy() nie zostanie wywołana tylko jeśli proces gospodarzem całej karty aplikacja zostanie zabita. Gdy proces zostanie zabity, wszystkie przydzielone mu zasoby są zwalniane, w związku z czym nie ma ryzyka wycieku pamięci w tym przypadku.

Ważna uwaga: od zwalniania zasobów w onDestroy() nie spowoduje wyciek pamięci, może to wyglądać jak dobry pomysł, aby umieścić tam wszystkie „puszczania” kod. Jednak rzadko jest to optymalne podejście. Czemu? Czytaj poniżej.

Po przejściu Activity do tła jest zatrzymany, ale nie zniszczony (zwykle). Activity może pozostać w tym stanie "zatrzymanym" przez dłuższy czas i zostanie ponownie uruchomiony, jeśli użytkownik powróci do aplikacji. Jeśli zwolnisz zasoby w onDestroy(), które nie są domyślnie wywoływane, gdy Activity przechodzi w tło, Activity będzie trzymać te zasoby w stanie zatrzymania, co spowoduje większą ilość zasobów zużywanych przez twoją aplikację w tle.

Gdy zabraknie pamięci w Androidzie, zaczyna zabijać procesy w celu uwolnienia zużytej przez nie pamięci. Jednym z najważniejszych czynników branych pod uwagę przy wyborze procesów do zabicia jest ich zużycie zasobów. Tak więc, jeśli twoja aplikacja trzyma zasoby, gdy jest w stanie zatrzymania w tle, będzie miała większą szansę na zabicie przez Androida.

Ponadto my, programiści, musimy się upewnić, że tworzymy najlepsze aplikacje dla naszych użytkowników. Aplikacja, która pochłania nie minimalną ilość zasobów telefonu użytkownika i baterii w tle, nie jest dobrą aplikacją. I użytkownicy będą o tym wiedzieć!

Dlatego zdecydowanie zalecam zwolnienie wszystkich zasobów w metodzie onStop(). Zwykle w ogóle nie zastępuję onDestroy() metod w Activities ani .

WNIOSEK: Jak podkreślił w swoim komentarzu @Juan, powyższy ważna uwaga ma równie ważną, ale nie tak oczywiste następstwo: onStart() powinna być jedyną metodą, w której zasoby są przydzielane. Bez względu na to, jaka jest twoja definicja "zasobów", ani onCreate() ani onResume() nie powinny przydzielać tych zasobów.

+2

Jedna dodatkowa uwaga, aby zachować spójność kodu. Zasoby nabyte w onCreate() powinny być wydane w onDestroy(). Zasoby nabyte w onResume() powinny być wydane w onPause(). To samo dla onStart() - onStop(). – Juan

+0

@Juan, to bardzo ważna uwaga, o której zapomniałem wyraźnie wspomnieć. Chciałem powiedzieć, że ani 'onCreate()', ani 'onResume()' nie powinny w ogóle alokować żadnych zasobów. Będę edytować odpowiedź. Dzięki – Vasiliy

+0

@Juan Nie zgadzam się z twoim oświadczeniem, ponieważ na przykład, jeśli zdobędziesz GPS w trybie onCreate, a twoja aplikacja przejdzie w stan pauzy, będzie nadal wykrywać GPS, którego NIE chcesz w większości przypadków. –

2

Myślę, że Wasilij dostarczył wspaniałej odpowiedzi. Nadal istnieje jeden mały, ale ważny punkt, że brakuje tam związane

  1. Czy to prawda, że ​​gdy Android zabija proces, że środki zostaną zniszczone i nie może dojść do wycieku (nawet wtedy, gdy nie udostępniliśmy jawnie zasobu?).

Odpowiedź zależy od tego, czego się dokładnie boisz. Vasily zwrócił uwagę, że Android (bazujący na Linuksie) jest nowoczesnym, bezpiecznym systemem operacyjnym, który gwarantuje, że po zabiciu procesu cała pamięć zostanie zwolniona, ponadto wszystkie otwarte pliki, połączenia sieciowe itp. Również zostaną poprawnie zamknięte. Więc nie będzie wycieku zasobów w zwykłym znaczeniu.

Nadal istnieje jeden potencjalnie problematyczny scenariusz. Załóżmy, że masz pewną logikę, którą wykonujesz po zwolnieniu części zasobu, czyli czegoś, co wstawisz do destruktora w C++ lub w implementacji Closeable.close w Javie. Na przykład masz pamięć podręczną w pamięci, która opóźnia zapis do pliku z grupowaniem. Zwykle opróżniasz pamięć podręczną w pamięci w numerze onDestroy i wszystko działa poprawnie. Ale kiedy proces zostanie siłą zabity przez Androida, onDestroy może nie zostać wywołany, a logika przepłukiwania nie zostanie wykonana, co może spowodować utratę danych i/lub niepoprawny stan w trwałym miejscu. Więc jeśli masz coś takiego, powinieneś zapewnić spójność, wykonując taką logikę w bardziej niezawodnym miejscu: lub onStop.