Gdy użytkownik porusza się po aplikacji, z niej i z powrotem do niej wraca,
Liczba instancji w Twojej aplikacji, które są przenoszone przez Activity
w różnych stanach w ich cyklu życia.
Klasa Activity
zawiera liczbę wywołań zwrotnych.
które powiadamiają aktywność o zmianie stanu lub o tym, że
tworzy, zatrzymuje lub wznawia działanie albo niszczy
proces, w którym znajduje się aktywność.
W ramach metod wywołania zwrotnego cyklu życia możesz zadeklarować, jak aktywność działa, gdy użytkownik opuści aktywność i ponownie do niej dołączy. Jeśli na przykład jesteś tworząc odtwarzacz strumieniowy, możesz wstrzymać odtwarzanie filmu i zakończyć połączenie sieciowe, gdy użytkownik przełącza się na inną aplikację. Gdy użytkownik wraca, możesz połączyć się ponownie z siecią i pozwolić użytkownikowi na wznowienie odtwarzania w tym samym miejscu.
Każde wywołanie zwrotne umożliwia wykonanie konkretnej czynności co jest właściwe dla danej zmiany stanu. Właściwa praca po prawej oraz czas potrzebny na dokonanie zmian zapewniających prawidłowe działanie aplikacji. Dobra implementacja wywołań zwrotnych cyklu życia może na przykład ułatwić Unikaj:
- Awaria, gdy użytkownik odbiera połączenie telefoniczne lub przełącza się na inne połączenie podczas używania aplikacji.
- Zużywanie cennych zasobów systemowych, gdy użytkownik nie jest aktywny za jego pomocą.
- Utrata postępów użytkownika, jeśli opuści on aplikację i wróci do niej później.
- Awaria lub utrata postępów użytkownika po obróceniu ekranu między orientacją poziomą i pionową.
W tym dokumencie szczegółowo opisujemy cykl życia aktywności. Rozpoczęcie tworzenia dokumentu przez opisanie paradygmatu cyklu życia. Następnie objaśniono każde z wywołań zwrotnych: co dzieje się wewnątrz firmy podczas wykonywania i co musisz wdrożyć, w trakcie ich trwania.
Następnie krótko omawia zależność między aktywnością oraz podatność procesu na wyłączenie się przez system. Omawiamy w nim również kilka tematów związanych z przejściami stanów aktywności.
Informacje o cyklach obsługi, w tym wskazówki dotyczące sprawdzonych metod można znaleźć w sekcji Obsługa cykli życia przy użyciu komponentów uwzględniających cykl życia i zapisywanie stanów interfejsu. Naucz się tworzyć solidną aplikację o wysokiej jakości produkcyjnej za pomocą działań w połączeniu z komponentami architektury, zobacz Przewodnik po architekturze aplikacji.
Pojęcia związane z cyklem aktywności i cyklem życia
Aby poruszać się między etapami cyklu życia aktywności,
Klasa Activity
zawiera podstawowy zestaw 6 wywołań zwrotnych:
onCreate()
,
onStart()
,
onResume()
,
onPause()
,
onStop()
i
onDestroy()
System wywołuje
każdego z tych wywołań zwrotnych, gdy aktywność przechodzi w nowy stan.
Rys. 1 przedstawia wizualną reprezentację tego paradygmatu.
Gdy użytkownik zaczyna opuszczać aktywność, system wywołuje metody do usunięcia aktywności. W niektórych przypadkach aktywność jest tylko częściowo jest zdemontowany i nadal pozostaje w pamięci, na przykład gdy użytkownik przełączy się na innej aplikacji. W takich przypadkach aktywność może nadal pojawić się na pierwszym planie.
Jeśli użytkownik wróci do aktywności, zostanie wznowiony od miejsca, w którym użytkownik przerwał. Poza kilkoma wyjątkami aplikacje są ograniczone od podczas uruchamiania działań w tle.
Prawdopodobieństwo, że system zabijanie danego procesu i wykonywanych w nim działań zależy od stanu aktywności w danym momencie. Więcej informacji o związku między władzami stanowymi lukę w zabezpieczeniach znajdziesz w sekcji o stanie działania i wyrzucie z pamięci.
W zależności od stopnia skomplikowania Twojej aktywności prawdopodobnie nie musisz wdrożenia wszystkich metod cyklu życia. Ważne jest jednak, aby zrozumieć każdy z nich i zaimplementować te, dzięki którym aplikacja będzie zgodnie z oczekiwaniami użytkowników.
Wywołania zwrotne cyklu życia
Ta sekcja zawiera informacje na temat koncepcji i wdrażania metod wywołania zwrotnego używanych w cyklu życia działania.
Niektóre działania należą do metod cyklu życia aktywności. Pamiętaj jednak, że kod miejsca implementujący działanie składnika zależnego w zamiast metody cyklu życia aktywności. Aby to zrobić, musisz z uwzględnieniem cyklu życia zależnego komponentu. Aby dowiedzieć się, jak zrobić z uwzględnieniem cyklu życia komponentów zależnych, zobacz Obsługa cykli życia dzięki komponentom uwzględniającym cykl życia.
onCreate()
Musisz zaimplementować to wywołanie zwrotne, które jest wywoływane, gdy system po raz pierwszy utworzy
działania. Po utworzeniu aktywności przechodzi ona w stan Utworzono.
W: onCreate()
wykonaj podstawową logikę uruchamiania aplikacji,
ma miejsce tylko raz w całym cyklu życia działania.
Na przykład plik
implementacja onCreate()
może wiązać dane z listami, wiązać działanie z tagiem
ViewModel
,
i utworzyć instancje zmiennych w zakresie klasy. Ta metoda otrzymuje
parametr savedInstanceState
, który jest wartością Bundle
obiekt z zapisanym wcześniej stanem aktywności. Jeśli aktywność ma
nigdy wcześniej nie istniał, wartość obiektu Bundle
ma wartość null.
Jeśli masz komponent uwzględniający cykl życia, który jest połączony z cyklem życia
Twojej aktywności, otrzyma ona
ON_CREATE
. Metoda z adnotacjami @OnLifecycleEvent
jest wywoływana, tak aby uwzględniała cykl życia
może wykonywać dowolny kod konfiguracji potrzebny do utworzenia stanu.
Przykład metody onCreate()
przedstawia podstawową konfigurację działań, np. zadeklarowanie interfejsu użytkownika
(zdefiniowanej w pliku układu XML), zdefiniować zmienne składowe i skonfigurować
i innych elementów interfejsu. W tym przykładzie plik układu XML przekazuje
identyfikator zasobu pliku R.layout.main_activity
do
setContentView()
Kotlin
lateinit var textView: TextView // Some transient state for the activity instance. var gameState: String? = null override fun onCreate(savedInstanceState: Bundle?) { // Call the superclass onCreate to complete the creation of // the activity, like the view hierarchy. super.onCreate(savedInstanceState) // Recover the instance state. gameState = savedInstanceState?.getString(GAME_STATE_KEY) // Set the user interface layout for this activity. // The layout is defined in the project res/layout/main_activity.xml file. setContentView(R.layout.main_activity) // Initialize member TextView so it is available later. textView = findViewById(R.id.text_view) } // This callback is called only when there is a saved instance previously saved using // onSaveInstanceState(). Some state is restored in onCreate(). Other state can optionally // be restored here, possibly usable after onStart() has completed. // The savedInstanceState Bundle is same as the one used in onCreate(). override fun onRestoreInstanceState(savedInstanceState: Bundle?) { textView.text = savedInstanceState?.getString(TEXT_VIEW_KEY) } // Invoked when the activity might be temporarily destroyed; save the instance state here. override fun onSaveInstanceState(outState: Bundle?) { outState?.run { putString(GAME_STATE_KEY, gameState) putString(TEXT_VIEW_KEY, textView.text.toString()) } // Call superclass to save any view hierarchy. super.onSaveInstanceState(outState) }
Java
TextView textView; // Some transient state for the activity instance. String gameState; @Override public void onCreate(Bundle savedInstanceState) { // Call the superclass onCreate to complete the creation of // the activity, like the view hierarchy. super.onCreate(savedInstanceState); // Recover the instance state. if (savedInstanceState != null) { gameState = savedInstanceState.getString(GAME_STATE_KEY); } // Set the user interface layout for this activity. // The layout is defined in the project res/layout/main_activity.xml file. setContentView(R.layout.main_activity); // Initialize member TextView so it is available later. textView = (TextView) findViewById(R.id.text_view); } // This callback is called only when there is a saved instance previously saved using // onSaveInstanceState(). Some state is restored in onCreate(). Other state can optionally // be restored here, possibly usable after onStart() has completed. // The savedInstanceState Bundle is same as the one used in onCreate(). @Override public void onRestoreInstanceState(Bundle savedInstanceState) { textView.setText(savedInstanceState.getString(TEXT_VIEW_KEY)); } // Invoked when the activity might be temporarily destroyed; save the instance state here. @Override public void onSaveInstanceState(Bundle outState) { outState.putString(GAME_STATE_KEY, gameState); outState.putString(TEXT_VIEW_KEY, textView.getText()); // Call superclass to save any view hierarchy. super.onSaveInstanceState(outState); }
Zamiast definiować plik XML i przesyłać go do setContentView()
, możesz
może tworzyć nowe obiekty View
w kodzie aktywności i budować
możesz wyświetlić hierarchię, wstawiając nowe obiekty View
do
ViewGroup
Aby użyć tego układu, przekaż
pierwiastek od ViewGroup
do setContentView()
.
Więcej informacji o tworzeniu interfejsu użytkownika znajdziesz w
interfejsu.
Twoja aktywność nie będzie widoczna w Utworzonych.
stanu. Gdy metoda onCreate()
zakończy wykonywanie, działanie pojawi się w polu Started (Rozpocznij)
a system wywołuje funkcję onStart()
i onResume()
metod szybko
w kolejności ich stosowania.
onStart()
Gdy aktywność przejdzie w stan rozpoczęcia, system
wywołuje funkcję onStart()
.
To wywołanie sprawia, że aktywność jest widoczna dla użytkownika jako
przygotowuje się do wejścia na pierwszy plan i wprowadzenia aktywności w interakcję.
Na przykład ta metoda polega na tym, że kod zachowuje
interfejs użytkownika.
Gdy działanie przejdzie do stanu Uruchomienie, każdy komponent uwzględniający cykl życia powiązany z danym cyklem życia będzie powiązany
do cyklu życia aktywności otrzymuje
ON_START
.
Metoda onStart()
kończy działanie
i, tak jak w przypadku stanu Utworzona, aktywność nie pozostaje
w stanie Rozpoczęte. Po zakończeniu tego wywołania zwrotnego aktywność
Wznowiono, a system wywołuje metodę
onResume()
.
onWznów()
Gdy działanie przejdzie w stan wznowiony, pojawi się na pierwszym planie.
system wywołuje metodę onResume()
oddzwanianie. Jest to stan, w którym aplikacja
wchodzi w interakcję z użytkownikiem. Aplikacja pozostaje w tym stanie, dopóki coś się nie stanie
użytkownik może skupić się na aplikacji, np. na urządzeniu odbierającym połączenie telefoniczne,
przejście do innej aktywności lub wyłączenie ekranu urządzenia.
Gdy działanie przejdzie do stanu Wznowienie, każdy komponent uwzględniający cykl życia powiązany z danym cyklem życia będzie powiązany
do cyklu życia aktywności otrzymuje
ON_RESUME
. W tym miejscu komponenty cyklu życia mogą uruchamiać dowolne funkcje, które powinny działać
komponent jest widoczny i znajduje się na pierwszym planie, np. uruchamia kamerę
podgląd.
Gdy wystąpi zdarzenie zakłócające, aktywność zostanie oznaczona jako Wstrzymano.
, a system wywołuje metodę
onPause()
oddzwonienie.
Jeśli aktywność wróci do
ze stanem Wstrzymano, system ponownie wywołuje metodę
Metoda onResume()
. Z tego powodu zastosuj
onResume()
, aby zainicjować komponenty udostępniane przez Ciebie podczas
onPause()
oraz wykonać inne
inicjalizacje, które muszą wystąpić za każdym razem, gdy działanie trafia do
stanu.
Oto przykład komponentu uwzględniającego cykl życia, który uzyskuje dostęp do kamery, gdy
komponent odbiera zdarzenie ON_RESUME
:
Kotlin
class CameraComponent : LifecycleObserver { ... @OnLifecycleEvent(Lifecycle.Event.ON_RESUME) fun initializeCamera() { if (camera == null) { getCamera() } } ... }
Java
public class CameraComponent implements LifecycleObserver { ... @OnLifecycleEvent(Lifecycle.Event.ON_RESUME) public void initializeCamera() { if (camera == null) { getCamera(); } } ... }
Poprzedni kod inicjuje kamerę, gdy
LifecycleObserver
odbiera zdarzenie ON_RESUME
. Aktywność w trybie wielu okien
mogą być w pełni widoczne nawet wtedy, gdy są wstrzymane. Na przykład, gdy
aplikacja jest w trybie wielu okien, a użytkownik klika okno, które nie
aktywność zostanie wstrzymana.
Jeśli
chcesz, aby kamera była aktywna tylko po wznowieniu aplikacji (widoczna)
i aktywny na pierwszym planie), a następnie zainicjuj kamerę po
ON_RESUME
zdarzenie
co pokazujemy. Jeśli chcesz, aby kamera pozostawała aktywna w trakcie aktywności
jest wstrzymana, ale widoczna, np. w trybie wielu okien, a następnie
zainicjować kamerę po wystąpieniu zdarzenia ON_START
.
Jednak samo korzystanie z aparatu aktywna, gdy aktywność jest wstrzymana, może odmówić dostępu do innej kamery Aplikacja została wznowiona w trybie wielu okien. Czasami konieczne jest zachowanie kamera jest aktywna w czasie wstrzymania aktywności, ale może spowolnić ogólne wrażenia użytkowników.
Dlatego dobrze się zastanów, gdzie w najodpowiedniejsze jest przejęcie kontroli nad współdzielonymi zasobami systemowymi w o kontekście trybu wielu okien. Dowiedz się więcej o obsłudze trybu wielu okien Więcej informacji znajdziesz w artykule Obsługa wielu okien.
Niezależnie od tego, jakie zdarzenie budowania zbioru danych wybierzesz,
operacji inicjowania, pamiętaj, aby użyć odpowiedniego cyklu życia
w celu zwolnienia zasobu. Jeśli zainicjujesz coś po
zdarzenia ON_START
, zwolnij je lub zatrzymaj po
ON_STOP
. Jeśli
zainicjuj po zdarzeniu ON_RESUME
, zwolnij po
ON_PAUSE
.
Poprzedni fragment kodu umieszcza kod inicjowania kamery w sekcji
uwzględniającym cykl życia. Zamiast tego możesz umieścić ten kod bezpośrednio w aktywności
wywołania zwrotnego cyklu życia, takie jak onStart()
czy
onStop()
, ale nie zalecamy tego. Dodaję tę logikę
niezależnego komponentu uwzględniającego cykl życia, umożliwi ponowne wykorzystanie tego komponentu
w wielu działaniach bez konieczności powielania kodu. Aby dowiedzieć się, jak utworzyć komponent uwzględniający cykl życia, przeczytaj artykuł
Obsługa cykli życia komponentów uwzględniających cykl życia.
onPause()
System wywołuje tę metodę jako pierwszą wskazówkę, że użytkownik opuszcza witrynę. Twojej aktywności, ale nie zawsze oznacza to jej zniszczenie. Wskazuje on, że aktywność nie jest już na pierwszym planie, ale widoczna jest widoczny dla użytkowników w trybie wielu okien. Aktywność może pojawić się z kilku powodów ten stan:
- Zdarzenie, które przerywa wykonywanie aplikacji, zgodnie z opisem w sekcji dotyczącej wywołanie zwrotne onWznów(), wstrzymuje bieżącą aktywność. To najczęstsze tych kwestii.
- W trybie wielu okien tylko jedna aplikacja jest zaznaczona w dowolnym momencie, a pozostałe aplikacje zostaną wstrzymane.
- Otwieranie nowej, półprzezroczystej aktywności, np. okna, wstrzyma aktywność, której dotyczy. Jeśli aktywność jest częściowo widoczna, ale nie jest wstrzymany.
Gdy działanie przejdzie w stan wstrzymania, każdy komponent uwzględniający cykl życia powiązany z kontem będzie powiązany
do cyklu życia aktywności otrzymuje
ON_PAUSE
. Tutaj
komponenty cyklu życia mogą zatrzymać dowolną funkcję, która nie musi działać
gdy komponent nie jest na pierwszym planie, np. zatrzymuje kamerę.
podgląd.
Użyj metody onPause()
, aby wstrzymać lub
dostosować operacje, które nie mogą być kontynuowane lub mogą być kontynuowane w ramach moderacji,
gdy Activity
jest w stanie wstrzymania i że
wkrótce zostaną wznowione.
Możesz też użyć metody onPause()
, aby
zwalniania zasobów systemowych, uchwytów czujników (np. GPS) ani żadnych zasobów, które
wpływa na żywotność baterii, gdy aktywność jest wstrzymana, a użytkownik nie
ich potrzebują.
Jednak jak wspomnieliśmy w sekcji dotyczącej onResume()
, Wstrzymana
aktywność może być nadal widoczna, jeśli aplikacja działa w trybie wielu okien.
Aby w pełni zwolnić lub dostosować, rozważ użycie onStop()
zamiast onPause()
zasoby i operacje związane z interfejsem, aby lepiej obsługiwać tryb wielu okien.
Oto przykład LifecycleObserver
reakcja na zdarzenie ON_PAUSE
jest odpowiednikiem poprzedniego zdarzenia
Przykład zdarzenia ON_RESUME
, który pozwala zwolnić kamerę, która uruchamia się po
odebrane zdarzenie ON_RESUME
:
Kotlin
class CameraComponent : LifecycleObserver { ... @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE) fun releaseCamera() { camera?.release() camera = null } ... }
Java
public class JavaCameraComponent implements LifecycleObserver { ... @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE) public void releaseCamera() { if (camera != null) { camera.release(); camera = null; } } ... }
W tym przykładzie kod zwalniający aparat umieszcza się po fragmencie
Zdarzenie ON_PAUSE
odebrało LifecycleObserver
.
Wykonanie onPause()
jest bardzo krótkie i
nie zawsze zapewnia dość czasu na wykonanie operacji zapisu. Do tego celu
Powód, nie używaj onPause()
do zapisywania aplikacji lub użytkownika
do analizy danych,
wykonywać wywołania sieciowe i wykonywać transakcje w bazie danych. Takie treści mogą nie być
przed zakończeniem metody.
Zamiast tego wykonuj bardzo duże operacje wyłączania w trakcie
onStop()
Więcej informacji na temat konfiguracji
na temat odpowiednich operacji do wykonania
onStop()
, więcej informacji znajdziesz w następnej sekcji. Więcej informacji o zapisywaniu
przeczytaj sekcję o zapisywaniu i przywracaniu stanu.
Zakończenie działania metody onPause()
nie oznacza, że aktywność pozostaje wstrzymana. Chodzi raczej o to, że aktywność
pozostaje w tym stanie do czasu wznowienia lub całkowitego
niewidoczne dla użytkownika. Jeśli aktywność zostanie wznowiona, system ponownie wywoła
wywołanie zwrotne onResume()
.
Jeśli
aktywność wraca ze stanu wstrzymania do stanu Wznowiono, system zachowuje
instancję Activity
znajdującą się w pamięci, przypominając
tę instancję, gdy system wywoła onResume()
.
W takiej sytuacji nie musisz ponownie inicjować komponentów utworzonych podczas
metody wywołania zwrotnego prowadzące do stanu wznowienia. Jeśli aktywność
całkowicie niewidoczne, system wywołuje
onStop()
onStop()
Gdy aktywność nie jest już widoczna dla użytkownika, w polu
Zatrzymana, a system wywołuje
onStop()
oddzwonienie. Może się tak zdarzyć, gdy nowo uruchomiona aktywność obejmuje cały ekran.
system wywołuje też funkcję onStop()
gdy działanie zakończy się i za chwilę się zakończy.
Gdy działanie przejdzie w stan zatrzymania, każdy komponent uwzględniający cykl życia powiązany z danym cyklem życia będzie powiązany z tym,
do cyklu życia aktywności otrzymuje
ON_STOP
. Tutaj
komponenty cyklu życia mogą zatrzymać dowolną funkcję, która nie musi działać
gdy komponent nie jest widoczny na ekranie.
W metodzie onStop()
zwolnij lub dostosuj
zasobów, które nie są potrzebne, gdy aplikacja nie jest widoczna dla użytkownika. Aplikacja może na przykład
wstrzymywać animacje i przełączać się ze szczegółowej na szczegółową aktualizację lokalizacji. Zastosowanie
onStop()
zamiast onPause()
oznacza, że praca związana z interfejsem jest kontynuowana, nawet gdy użytkownik przegląda Twoją aktywność w trybie wielu okien.
i trybu uzyskiwania zgody.
Oprócz tego użyj usługi onStop()
do wykonywania operacji wyłączania obciążających procesor. Na przykład, jeśli
nie ma lepszego czasu na zapisanie informacji w bazie danych,
możesz to zrobić w czasie onStop()
.
Poniższy przykład pokazuje implementację funkcji
onStop()
, który zapisuje zawartość pliku
wersja robocza notatki do pamięci trwałej:
Kotlin
override fun onStop() { // Call the superclass method first. super.onStop() // Save the note's current draft, because the activity is stopping // and we want to be sure the current note progress isn't lost. val values = ContentValues().apply { put(NotePad.Notes.COLUMN_NAME_NOTE, getCurrentNoteText()) put(NotePad.Notes.COLUMN_NAME_TITLE, getCurrentNoteTitle()) } // Do this update in background on an AsyncQueryHandler or equivalent. asyncQueryHandler.startUpdate( token, // int token to correlate calls null, // cookie, not used here uri, // The URI for the note to update. values, // The map of column names and new values to apply to them. null, // No SELECT criteria are used. null // No WHERE columns are used. ) }
Java
@Override protected void onStop() { // Call the superclass method first. super.onStop(); // Save the note's current draft, because the activity is stopping // and we want to be sure the current note progress isn't lost. ContentValues values = new ContentValues(); values.put(NotePad.Notes.COLUMN_NAME_NOTE, getCurrentNoteText()); values.put(NotePad.Notes.COLUMN_NAME_TITLE, getCurrentNoteTitle()); // Do this update in background on an AsyncQueryHandler or equivalent. asyncQueryHandler.startUpdate ( mToken, // int token to correlate calls null, // cookie, not used here uri, // The URI for the note to update. values, // The map of column names and new values to apply to them. null, // No SELECT criteria are used. null // No WHERE columns are used. ); }
Poprzedni przykładowy kod bezpośrednio korzysta z SQLite. Zalecamy jednak korzystanie z funkcji Pokój, bibliotekę trwałości, która zapewnia warstwę abstrakcji zamiast SQLite. Aby się uczyć o zaletach korzystania z usługi Room i o tym, jak ją wdrożyć w aplikacji, zobacz Biblioteka trwałości sal Google.
Gdy aktywność przejdzie w stan Zatrzymana, Activity
obiekt jest przechowywany w pamięci: zachowuje wszystkie stany i elementy składowe
informacje, ale nie jest powiązany z menedżerem okien. Gdy aktywność
przypomina mu tę informację.
Nie musisz
ponownie zainicjuj komponenty utworzone przy użyciu dowolnej metody wywołania zwrotnego
prowadzące do stanu Wznowiono. System śledzi również bieżący
dla każdego obiektu View
w układzie, więc jeśli
użytkownik wpisuje tekst do widżetu EditText
, który
są zachowywane, więc nie musisz ich zapisywać ani przywracać.
Uwaga: po zatrzymaniu aktywności system
może zniszczyć proces zawierający aktywność, jeśli system
musi odzyskać pamięć.
Nawet jeśli system zniszczy proces w trakcie działania
zostanie zatrzymany, system zachowa stan View
takich jak tekst w widżecie EditText
, w sekcji
Bundle
– obiekt blob z parami klucz-wartość – i przywraca je.
jeśli użytkownik powróci do aktywności. Dla:
więcej informacji o przywracaniu aktywności, do której wróci użytkownik, znajdziesz w
sekcji o zapisywaniu i przywracaniu stanu.
Po zatrzymaniu aktywność wraca do
użytkownika lub działanie zostało zakończone i przestaje działać. Jeśli aktywność
system wywołuje funkcję onRestart()
.
Po zakończeniu działania funkcji Activity
system wywołuje
onDestroy()
onDestroy()
Funkcja onDestroy()
jest wywoływana przed
System wywołuje to wywołanie zwrotne z jednego z dwóch powodów:
-
Działanie dobiega końca, ponieważ użytkownik całkowicie odrzuci
aktywności lub z powodu
finish()
jest wywołano aktywność. - System tymczasowo niszczy aktywność ze względu na konfigurację takich jak obrót urządzenia czy przejście w tryb wielu okien.
Gdy działanie przejdzie do stanu zniszczenia, każdy komponent uwzględniający cykl życia powiązany z danym cyklem życia
do cyklu życia aktywności otrzymuje
ON_DESTROY
. Tutaj
komponenty cyklu życia mogą oczyścić wszystko, czego potrzebują,
Element Activity
został zniszczony.
Zamiast używać funkcji logicznych w elemencie Activity
, aby określić powód zniszczenia,
użyj obiektu ViewModel
do umieszczenia
istotne dane widoku dotyczące Activity
. Jeśli Activity
został utworzony ponownie
ze względu na zmianę konfiguracji ViewModel
nie musi nic robić, ponieważ
jest zachowywany i przekazany do następnej instancji Activity
.
Jeśli Activity
nie zostanie odtworzony, ViewModel
będzie mieć parametr
jest wywoływana metoda onCleared()
, gdzie
może oczyścić wszystkie potrzebne dane przed zniszczeniem. Możesz rozróżnić te 2 scenariusze za pomocą
isFinishing()
.
Jeśli działanie dobiega końca, onDestroy()
jest ostatnim wywołaniem zwrotnym cyklu życia
które otrzymujemy. Jeśli funkcja onDestroy()
jest wywoływana w wyniku konfiguracji
systemu, system natychmiast tworzy nowe wystąpienie działania i wywołuje
onCreate()
dla tej nowej instancji w nowej konfiguracji.
Wywołanie zwrotne onDestroy()
zwalnia wszystkie zasoby, które nie zostały zwolnione wcześniej
wywołań zwrotnych, na przykład onStop()
.
Stan aktywności i wyrzucenie z pamięci
System wstrzymuje procesy, gdy muszą zwolnić pamięć RAM. Prawdopodobieństwo, że układ zabijanie danego procesu zależy od stanu procesu w momencie, w którym się on znajduje. Stan procesu, z kolei zależy od stanu uruchomionego działania. Tabela 1 przedstawia korelacje między stanem procesu, aktywnością oraz prawdopodobieństwo zakończenia procesu przez system. Ta tabela ma zastosowanie tylko wtedy, gdy proces nie uruchamia innych typów komponentów aplikacji.
Prawdopodobieństwo zabicia | Stan procesu | Stan ostatniej aktywności |
---|---|---|
Najniższy | Pierwszy plan (co ma się wyostrzyć lub uzyskać fokus) | Wznowiono |
Niska | Widoczne (bez zaznaczenia) | Uruchomiona/wstrzymana |
Wyższa | Tło (niewidoczne) | Zatrzymano |
Najwyższa | Puste | Zniszczono |
Tabela 1. Związek między cyklem życia procesu a stanem działania.
System nigdy nie kończy działania bezpośrednio, aby zwolnić pamięć. Zamiast tego zabija proces, w którym działa aktywność, niszcząc nie tylko działanie ale też wszystkie inne elementy tego procesu. Aby dowiedzieć się, jak zachować i przywróć stan UI aktywności po zainicjowaniu przez system śmierci procesu przeczytaj sekcję o zapisywaniu i przywracaniu stanu.
Użytkownik może też zakończyć proces, używając Menedżera aplikacji w sekcji Ustawienia, aby wyłączyć odpowiednią aplikację.
Więcej informacji o procesach znajdziesz w artykule Procesy i wątki .
Zapisywanie i przywracanie tymczasowego stanu interfejsu
Użytkownik oczekuje, że stan interfejsu działania pozostanie niezmieniony przez cały zmian konfiguracji, takich jak obrót lub przejście do trybu wielu okien. System domyślnie niszczy jednak aktywność, gdy taka konfiguracja i zostaną usunięte wszystkie stany interfejsu użytkownika zapisane w instancji aktywności.
Użytkownik oczekuje też, że stan UI pozostanie taki sam, jeśli tymczasowo przełącz się z aplikacji na inną i wróć do swojej aplikacji później. System może jednak zniszczyć proces aplikacji, gdy Użytkownika nie ma przy komputerze, a Twoja aktywność została zatrzymana.
Gdy ograniczenia systemu zniszczą aktywność, zachowaj
tymczasowy stan interfejsu użytkownika za pomocą kombinacji funkcji
ViewModel
.
onSaveInstanceState()
,
i/lub pamięci lokalnej. Aby uzyskać więcej informacji na temat oczekiwań użytkowników w porównaniu z systemem
i jak najlepiej zachować złożone dane o stanie
aktywność inicjowana przez system i śmierć procesu, patrz
Zapisywanie stanów interfejsu.
W tej sekcji dowiesz się, jaki jest stan instancji i jak wdrożyć
onSaveInstance()
, która jest wywołaniem zwrotnym samej aktywności. Jeśli
Dane interfejsu są niewielkie – aby utrzymać interfejs użytkownika, wystarczy użyć samego pliku onSaveInstance()
.
zarówno po zmianach w konfiguracji, jak i po zainicjowaniu procesu zainicjowanego przez system.
Ponieważ jednak usługa onSaveInstance()
wiąże się z kosztami serializacji/deserializacji,
w większości przypadków używasz zarówno ViewModel
, jak i onSaveInstance()
, jako
opisane w artykule
Zapisz stany interfejsu.
Uwaga: aby dowiedzieć się więcej o zmianach konfiguracji i o tym, jak ograniczyć aktywność w razie potrzeby i sposobu reagowania na zmiany konfiguracji Wyświetl system i Jetpack Compose, zapoznaj się z Obsługuj zmiany konfiguracji.
Stan instancji
W kilku przypadkach Twoja aktywność zostaje zniszczona w wyniku działania normalnej aplikacji
na przykład gdy użytkownik naciśnie przycisk Wstecz lub
wysyła sygnał do własnego zniszczenia, wywołując
finish()
.
Gdy Twoja aktywność zostanie zniszczona, ponieważ użytkownik naciśnie Wstecz
działanie zakończy się samoczynnie, zarówno system, jak i użytkownik.
że instancja Activity
zniknęła na zawsze. W tych
w różnych scenariuszach, oczekiwania użytkownika odpowiadają działaniu systemu i nie musisz
nie musisz robić nic więcej.
Jeśli jednak system zniszczy aktywność z powodu ograniczeń systemu (np.
zmiany konfiguracji lub wykorzystania pamięci), mimo że rzeczywiste
Activity
nie istnieje, system pamięta, że ona istniała. Jeśli użytkownik spróbuje
powróci do aktywności, system utworzy jej nowe wystąpienie
aktywność wykorzystująca zbiór zapisanych danych opisujących jej stan
kiedy została zniszczona.
Zapisane dane, których system używa do przywrócenia
poprzedni stan jest nazywany stanem instancji. To kolekcja
par klucz-wartość przechowywanych w obiekcie Bundle
. Domyślnie atrybut
system używa stanu instancji Bundle
do zapisywania informacji
o każdym obiekcie View
w układzie aktywności, takim jak
wartość tekstową wpisaną w
Widżet EditText
.
Jeśli więc instancja aktywności zostanie zniszczona i odtworzona, stan układu to Przywrócono poprzedni stan bez konieczności podawania przez Ciebie kodu. Twoja aktywność może zawierać więcej informacji o stanie, które chcesz przywrócić, takich jak zmiennych członków, które śledzą postępy użytkownika w wykonywaniu czynności.
Uwaga: aby system Android przywrócił stan
widoków danych w Twojej aktywności, każdy z nich musi mieć unikalny identyfikator pochodzący od
w atrybucie android:id
.
Obiekt Bundle
nie jest odpowiedni do przechowywania więcej niż
To trywialna ilość danych, ponieważ wymaga serializacji w wątku głównym i pobiera
w pamięci procesów systemowych. Aby zachować więcej niż bardzo małą ilość danych,
stosując połączone podejście do zachowania danych, stosując trwałe metody
pamięci masowej, metodę onSaveInstanceState()
i
ViewModel
zajęcia, jak opisano w:
Zapisz stany interfejsu.
Zapisz prosty stan interfejsu za pomocą onSaveInstanceState()
Gdy aktywność się zatrzyma, system wywołuje metodę
onSaveInstanceState()
, dzięki czemu aktywność może zapisywać informacje o stanie w stanie instancji
w pakiecie. Domyślna implementacja tej metody zapisuje zmiany tymczasowe
informacje o stanie hierarchii widoków aktywności, takie jak
tekstu w widżecie EditText
lub pozycji przewijania w elemencie
Widżet ListView
.
Aby zapisać dodatkowe informacje o stanie instancji dla swojej aktywności, zastąp
onSaveInstanceState()
i dodaj pary klucz-wartość do zapisanego obiektu Bundle
.
w przypadku nieoczekiwanego zniszczenia Twojej aktywności. Po zastąpieniu
onSaveInstanceState()
, musisz wywołać implementację superklasy
jeśli chcesz, aby domyślna implementacja zapisywała stan hierarchii widoków.
Widać to w tym przykładzie:
Kotlin
override fun onSaveInstanceState(outState: Bundle?) { // Save the user's current game state. outState?.run { putInt(STATE_SCORE, currentScore) putInt(STATE_LEVEL, currentLevel) } // Always call the superclass so it can save the view hierarchy state. super.onSaveInstanceState(outState) } companion object { val STATE_SCORE = "playerScore" val STATE_LEVEL = "playerLevel" }
Java
static final String STATE_SCORE = "playerScore"; static final String STATE_LEVEL = "playerLevel"; // ... @Override public void onSaveInstanceState(Bundle savedInstanceState) { // Save the user's current game state. savedInstanceState.putInt(STATE_SCORE, currentScore); savedInstanceState.putInt(STATE_LEVEL, currentLevel); // Always call the superclass so it can save the view hierarchy state. super.onSaveInstanceState(savedInstanceState); }
Uwaga:
onSaveInstanceState()
to nie
wywołana, gdy użytkownik wyraźnie zakończy działanie lub w innych przypadkach, gdy
Funkcja finish()
jest wywoływana.
Aby zapisać trwałe dane, takie jak preferencje użytkownika lub dane bazy danych:
korzystaj z odpowiednich możliwości, gdy Twoja aktywność znajduje się na pierwszym planie.
Jeśli nie pojawi się taka możliwość, zapisz trwałe dane przez okres
onStop()
.
Przywróć stan w UI aktywności przy użyciu stanu zapisanej instancji
Jeśli Twoja aktywność zostanie odtworzona po uprzednim zniszczeniu,
może przywrócić zapisany stan instancji z instancji Bundle
,
do Twojej aktywności. Zarówno
onCreate()
i
.
onRestoreInstanceState()
metody wywołania zwrotnego otrzymują ten sam element Bundle
, który zawiera
informacje o stanie instancji.
Ponieważ metoda onCreate()
jest
czy system tworzy nowe wystąpienie Twojej aktywności
lub odtwarzając poprzednie, musisz sprawdzić, czy stan Bundle
ma wartość null przed próbą odczytania. Jeśli ma wartość null, system
tworzy nowe wystąpienie aktywności, zamiast przywrócić
i poprzednia, która została zniszczona.
Fragment kodu poniżej pokazuje, jak przywrócić niektóre
dane o stanie w onCreate()
:
Kotlin
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // Always call the superclass first // Check whether we're recreating a previously destroyed instance. if (savedInstanceState != null) { with(savedInstanceState) { // Restore value of members from saved state. currentScore = getInt(STATE_SCORE) currentLevel = getInt(STATE_LEVEL) } } else { // Probably initialize members with default values for a new instance. } // ... }
Java
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // Always call the superclass first // Check whether we're recreating a previously destroyed instance. if (savedInstanceState != null) { // Restore value of members from saved state. currentScore = savedInstanceState.getInt(STATE_SCORE); currentLevel = savedInstanceState.getInt(STATE_LEVEL); } else { // Probably initialize members with default values for a new instance. } // ... }
Zamiast przywracania stanu w okresie
onCreate()
, możesz zdecydować się na wdrożenie
onRestoreInstanceState()
, które system wywołuje po parametrze
onStart()
. System wywołuje
onRestoreInstanceState()
tylko jeśli jest zapisany stan do przywrócenia, więc
nie trzeba sprawdzać, czy Bundle
ma wartość null.
Kotlin
override fun onRestoreInstanceState(savedInstanceState: Bundle?) { // Always call the superclass so it can restore the view hierarchy. super.onRestoreInstanceState(savedInstanceState) // Restore state members from saved instance. savedInstanceState?.run { currentScore = getInt(STATE_SCORE) currentLevel = getInt(STATE_LEVEL) } }
Java
public void onRestoreInstanceState(Bundle savedInstanceState) { // Always call the superclass so it can restore the view hierarchy. super.onRestoreInstanceState(savedInstanceState); // Restore state members from saved instance. currentScore = savedInstanceState.getInt(STATE_SCORE); currentLevel = savedInstanceState.getInt(STATE_LEVEL); }
Uwaga: zawsze wywołaj implementację superklasy
onRestoreInstanceState()
aby domyślna implementacja mogła przywrócić stan hierarchii widoków.
Przechodzenie między aktywnościami
Aplikacja może zakończyć działanie, prawdopodobnie wiele razy, od początku korzystania z aplikacji, np. gdy użytkownik kliknie na urządzeniu przycisk Wstecz. lub powoduje uruchomienie innej aktywności.
Ta sekcja zawiera tematy, które należy znać, aby skutecznie przeprowadzić migrację. Tematy te obejmują rozpoczynanie aktywności na podstawie innej aktywności, zapisywanie aktywności i przywrócenie stanu aktywności.
Rozpoczynanie jednej aktywności od innej
Działanie często musi w pewnym momencie rozpocząć się od kolejnej. Ta potrzeba pojawia się, np. gdy aplikacja musi przejść z bieżącego ekranu do nowy.
W zależności od tego, czy nowa aktywność wymaga uzyskania konkretnych wyników
gdy ma się rozpocząć, rozpoczynasz nową aktywność za pomocą
startActivity()
lub
startActivityForResult()
. W obu przypadkach należy przekazać obiekt Intent
.
Obiekt Intent
określa dokładną wartość
działanie, które chcesz wykonać, lub opisuje rodzaj działania, które chcesz wykonać.
System wybiera dla Ciebie odpowiednią aktywność, która może być nawet
z innej aplikacji. Obiekt Intent
może
ale pobierają też niewielkie ilości danych,
które są wykorzystywane przez inicjowaną aktywność.
Więcej informacji o zajęciach Intent
znajdziesz w artykule
Zamiar i zamiary
Filtry.
startActivity()
Jeśli nowo rozpoczęte działanie nie musi zwracać wyniku, bieżące działanie może je rozpocząć
wywołując metodę
startActivity()
.
Pracując we własnej aplikacji, często musisz po prostu uruchomić znane działanie.
Na przykład z tego fragmentu kodu dowiesz się, jak uruchomić działanie o nazwie
SignInActivity
Kotlin
val intent = Intent(this, SignInActivity::class.java) startActivity(intent)
Java
Intent intent = new Intent(this, SignInActivity.class); startActivity(intent);
Aplikacja może też wykonywać pewne działania, takie jak wysyłanie e-maili, SMS-ów czy aktualizacji stanu, korzystając z danych o Twojej aktywności. W takim przypadku aplikacja może nie mieć własnych działań do wykonywania takich działań. Możesz korzystać z aktywności oferowanych przez inne aplikacje na urządzeniu, może wykonywać działania za Ciebie.
To właśnie wtedy intencje są bardzo ważne. Możesz utworzyć opisującą działanie, które chcesz wykonać, a system uruchamia odpowiednią aktywność z innej aplikacji. Jeśli istnieje wiele działań, które mogą obsłużyć intencję, użytkownik może wybrać, którego chce użyć. Jeśli na przykład chcesz pozwolić użytkownikowi na wysyłanie możesz utworzyć następującą intencję:
Kotlin
val intent = Intent(Intent.ACTION_SEND).apply { putExtra(Intent.EXTRA_EMAIL, recipientArray) } startActivity(intent)
Java
Intent intent = new Intent(Intent.ACTION_SEND); intent.putExtra(Intent.EXTRA_EMAIL, recipientArray); startActivity(intent);
Dodatkowym elementem EXTRA_EMAIL
dodanym do intencji jest tablica ciągu znaków
adresy e-mail, na które ma zostać wysłany e-mail. Gdy aplikacja pocztowa
odpowiada na tę intencję, odczytuje tablicę ciągu znaków podaną w dodatkowych parametrach i
umieszcza adresy w kolekcji „do” formularza tworzenia e-maila. W tym
działanie aplikacji do obsługi poczty e-mail rozpocznie się, a gdy skończy,
aktywność zostanie wznowiona.
startActivityForResult()
Czasami chcesz otrzymać wynik z aktywności po jej zakończeniu. Możesz na przykład zacząć
aktywność, która pozwala użytkownikowi wybrać osobę z listy kontaktów. Po zakończeniu zwraca
osoby, która została wybrana. W tym celu musisz wywołać metodę
startActivityForResult(Intent, int)
gdzie
parametr będący liczbą całkowitą.
Ten identyfikator służy do rozróżniania wywołań funkcji
startActivityForResult(Intent, int)
z tej samej aktywności. Nie jest to identyfikator globalny
że nie występuje konflikt z innymi aplikacjami ani działaniami. Wynik jest podany przez
onActivityResult(int, int, Intent)
.
Gdy aktywność dziecka zakończy się, może wywołać metodę setResult(int)
w celu:
zwraca dane do elementu nadrzędnego.
Aktywność podrzędna musi dawać kod wyniku, który może być wynikami standardowymi.
RESULT_CANCELED
, RESULT_OK
lub dowolne wartości niestandardowe
od RESULT_FIRST_USER
.
Ponadto
aktywność podrzędna może opcjonalnie zwrócić Intent
który zawiera wszelkie dodatkowe dane, których potrzebuje. Aktywność rodzica korzysta z parametrów
onActivityResult(int, int, Intent)
wraz z liczbą całkowitą określającą, że dana aktywność nadrzędna
w celu otrzymania informacji.
Jeśli aktywność dziecka nie powiedzie się z jakiegokolwiek powodu, na przykład w jego wyniku, rodzic
działanie otrzymuje wynik z kodem RESULT_CANCELED
.
Kotlin
class MyActivity : Activity() { // ... override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean { if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) { // When the user center presses, let them pick a contact. startActivityForResult( Intent(Intent.ACTION_PICK,Uri.parse("content://contacts")), PICK_CONTACT_REQUEST) return true } return false } override fun onActivityResult(requestCode: Int, resultCode: Int, intent: Intent?) { when (requestCode) { PICK_CONTACT_REQUEST -> if (resultCode == RESULT_OK) { // A contact was picked. Display it to the user. startActivity(Intent(Intent.ACTION_VIEW, intent?.data)) } } } companion object { internal val PICK_CONTACT_REQUEST = 0 } }
Java
public class MyActivity extends Activity { // ... static final int PICK_CONTACT_REQUEST = 0; public boolean onKeyDown(int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) { // When the user center presses, let them pick a contact. startActivityForResult( new Intent(Intent.ACTION_PICK, new Uri("content://contacts")), PICK_CONTACT_REQUEST); return true; } return false; } protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == PICK_CONTACT_REQUEST) { if (resultCode == RESULT_OK) { // A contact was picked. Display it to the user. startActivity(new Intent(Intent.ACTION_VIEW, data)); } } } }
Koordynowanie działań
Gdy jedno działanie rozpoczyna inne, w obu następuje zmiany w cyklu życia. Pierwsza aktywność przestaje działać i przechodzi w stan wstrzymania lub wstrzymania, a druga aktywność. Jeśli te aktywności udostępniają dane zapisane na dysku lub w innym miejscu, należy pamiętać, że pierwsza aktywność nie jest całkowicie zatrzymana przed drugą po utworzeniu konta. Rozpoczęcie drugiego etapu nakłada się natomiast z procesem zatrzymując pierwsze.
Kolejność wywołań zwrotnych w cyklu życia jest dobrze zdefiniowana, zwłaszcza gdy 2 działania są w ramach tego samego procesu, czyli w tej samej aplikacji, a jedna uruchamia drugą. Oto kolejność wykonywanych operacji gdy aktywność A rozpoczyna aktywność B:
- Metoda
onPause()
aktywności A jest wykonywana. onCreate()
użytkownika B,onStart()
i Metody (onResume()
) wykonywane w sekwencji. Aktywność B skupia się teraz na użytkownikach.- Jeśli Aktywność A nie jest już widoczna na ekranie, uruchomiona jest jej metoda
onStop()
.
Ta sekwencja wywołań zwrotnych cyklu życia pozwala zarządzać przejściem informacji z jednej aktywności do drugiej.