Lekcja 5.4. Odtwarzanie aktywności w Androidzie

> Dodaj do ulubionych

Istnieje kilka sytuacji, w których dochodzi do zniszczenia aktywności w wyniku normalnego funkcjonowania aplikacji, np. po naciśnięciu przez użytkownika przycisku Wstecz, bądź po zasygnalizowaniu przez aktywność końca pracy poprzez metodę finish(). System może także zniszczyć aktywność, która jest w danej chwili zatrzymana i nie była używana od dłuższego czasu, a także jeśli aktywność uruchomiona na pierwszym planie potrzebuje większych zasobów — aby zwolnić pamięć system musi wówczas zakończyć procesy wykonywane w tle.

Kiedy aktywność zostaje zniszczona w wyniku naciśnięcia przez użytkownika przycisku Wstecz lub jeśli sama zakończy działanie, system trwale usuwa ślad po danej instancji, ponieważ zachowanie programu wskazuje na to, że jest ona zbędna. Jeśli jednak aktywność zostaje zniszczona ze względu na ograniczenia systemowe (a nie w wyniku normalnego funkcjonowania aplikacji), wówczas bieżąca instancja zostaje usunięta, jednak system zapamiętuje, że kiedyś istniała. Jeśli zatem użytkownik wróci do danej aktywności, system utworzy jej nową instancję wykorzystując przy tym zapisane dane na temat jej ostatniego stanu. Dane służące do odzyskania stanu aktywności nazywane są „stanem instancji” i stanowią zbiór par klucz-wartość przechowywany w obiekcie Bundle.

Domyślnie w stanie instancji z obiektu Bundle system zapisuje informacje na temat każdego obiektu klasy View składającego się na układ aplikacji (np. wartości tekstowe wprowadzone do obiektu EditText). Jeśli dojdzie zatem do zniszczenia i odtworzenia instancji aktywności, system przywróci ostatni stan układu aplikacji bez korzystania z dodatkowego kodu. Może się jednak zdarzyć, że przywracanie całego zapisanego stanu jest zbędne, np. zmiennych składowych dotyczących postępu użytkownika.

Dodatkowe dane dotyczące stanu aktywności zapisuje się poprzez przedefiniowanie metody zwrotnej onSaveInstanceState(). Jest ona wywołana kiedy użytkownik opuszcza aktywność — jej stan zostaje zapisany w obiekcie Bundle na wypadek nieoczekiwanego zniszczenia aktywności. Jeśli system będzie musiał później odtworzyć jej egzemplarz, ten sam obiekt Bundle zostanie przekazany zarówno do metody onRestoreInstanceState() jak i onCreate().

odtwarzanie aktywności
Rysunek 1. Podczas zatrzymywania aktywności system wywołuje metodę onSaveInstanceState() (1), dzięki czemu możesz określić, jakie dodatkowe dane mają zostać przywrócone w przypadku odtworzenia stanu aktywności. Jeśli po zniszczeniu aktywności chcesz odtworzyć jej pełen ostatni egzemplarz, system przekaże zdefiniowane w punkcie (1) dane dot. stanu zarówno metodzie onCreate() jak i onRestoreInstanceState() (3)

Zapisywanie stanu aktywności

Kiedy następuje zatrzymanie aktywności, system wywołuje metodę onSaveInstanceState(), aby zapisać dane dotyczące stanu aktywności w zestawie par klucz-warość. W domyślnej implementacji metody zapisane zostają informacje na temat stanu hierarchii widoków, np. tekstu w widżecie EditText bądź pozycji suwaka w elemencie ListView.

Aby zapisać dodatkowe informacje na temat stanu aktywności, należy zaimplementować metodę onSaveInstanceState() i dodać do obiektu Bundle pary klucz-warość. Przykład:

static final String STATE_SCORE = "playerScore";
static final String STATE_LEVEL = "playerLevel";
...

@Override
public void onSaveInstanceState(Bundle savedInstanceState) {
    // zapisz aktualny stan gry użytkownika
    savedInstanceState.putInt(STATE_SCORE, mCurrentScore);
    savedInstanceState.putInt(STATE_LEVEL, mCurrentLevel);
    
    // zawsze wywołuj nadklasę, aby zapisać stan hierarchii widoków
    super.onSaveInstanceState(savedInstanceState);
}

Przywracanie stanu aktywności

Jeśli zniszczona aktywność zostanie odtworzona, możesz przywrócić jej stan zapisany w obiekcieBundle, który jest przekazywany do aktywności przez system. Metody zwrotne onCreate() i onRestoreInstanceState() otrzymują ten sam obiekt Bundle zawierający informacje na temat stanu danego egzemplarza aktywności.

System wywołuje metodę onCreate() podczas tworzenia nowej instancji aktywności lub odtwarzania wcześniejszego egzemplarza, dlatego przed próbą odczytania obiektu Bundle musisz sprawdzić, czy jest pusty. W takim wypadku nie będzie próbował przywrócić zniszczonego wystąpienia aktywności, lecz utworzy nowy egzemplarz.

Oto przykład odzyskiwania danych dotyczących stanu poprzez metodę onCreate():

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState); // zawsze wywołuj metodę z nadklasy jako pierwszą
   
    // sprawdź, czy można odtworzyć zniszczone wcześniej wystąpienie
    if (savedInstanceState != null) {
        // przywróć wartości składowych z zapisanego stanu
        mCurrentScore = savedInstanceState.getInt(STATE_SCORE);
        mCurrentLevel = savedInstanceState.getInt(STATE_LEVEL);
    } else {
        // prawdopodobnie dla nowej instancji zostaną zainicjowane składowe z wartościami domyślnymi
    }
    ...
}

Oprócz metody onCreate() do odtworzenia stanu aktywności można zaimplementować metodę onRestoreInstanceState(), która jest wywoływana przez system po metodzie onStart(). System wywoła onRestoreInstanceState() tylko jeśli stan do przywrócenia został wcześniej zapisany. Nie trzeba więc sprawdzać, czy obiekt Bundle jest pusty:

public void onRestoreInstanceState(Bundle savedInstanceState) {
    // zawsze wywołuj metodę z nadklasy, aby można było przywrócić stan hierarchii widoków
    super.onRestoreInstanceState(savedInstanceState);
   
    // przywróć składowe stanu z zapisanego egzemplarza
    mCurrentScore = savedInstanceState.getInt(STATE_SCORE);
    mCurrentLevel = savedInstanceState.getInt(STATE_LEVEL);
}

Aby dowiedzieć się więcej o odtwarzaniu stanu aktywności w przypadku jej ponownego uruchomienia w czasie wykonywania (np. w wyniku zmiany orientacji ekranu), przeczytaj artykuł Obsługa zmian w czasie wykonywania.

Autor: Google

Źródło: https://developer.android.com/training/basics/activity-lifecycle/recreating.html

Tłumaczenie: Joanna Liana

Treść tej strony jest dostępna na zasadach licencji CC BY 2.5