Cykl życia aktywności

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.

Rysunek 1. Uproszczona ilustracja przedstawiająca cykl życia aktywności.

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:

  1. Działanie dobiega końca, ponieważ użytkownik całkowicie odrzuci aktywności lub z powodu finish() jest wywołano aktywność.
  2. 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:

  1. Metoda onPause() aktywności A jest wykonywana.
  2. onCreate() użytkownika B, onStart() i Metody (onResume()) wykonywane w sekwencji. Aktywność B skupia się teraz na użytkownikach.
  3. 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.