W tej lekcji
- Specyfika wywołań zwrotnych cyklu życia
- Określanie aktywności startowej
- Tworzenie nowego obiektu aktywności
- Niszczenie aktywności
Warto przeczytać
- Przewodnik po aktywnościach (ang.)
Demo
W odróżnieniu od innych paradygmatów programowania, w których aplikacje są uruchamiane za pomocą metody main()
system Android inicjuje kod w obiekcie aktywności poprzez wywoływanie konkretnych metod zwrotnych, które odnoszą się do poszczególnych etapów cyklu życia aktywności. Istnieje sekwencja metod zwrotnych, które uruchamiają aktywność, a także takich, które ją niszczą.
Poniższa lekcja zawiera omówienie najważniejszych metod cyklu życia i pokazuje, jak obsłużyć pierwsze wywołanie zwrotne cyklu, które tworzy nowy obiekt aktywności.
Specyfika wywołań zwrotnych cyklu życia
W trakcie życia aplikacji system wywołuje podstawowe metody cyklu życia w sekwencji przypominającej piramidę schodkową — każdy schodek reprezentuje osobny etap cyklu. Za każdym razem, gdy system tworzy nowe wystąpienie aktywności każda metoda wywołania zwrotnego przesuwa jej stan o jeden schodek wyżej. Szczyt piramidy osiągany jest w momencie, gdy aktywność zostaje uruchomiona na pierwszym planie i jest w pełni dostępna dla użytkownika.
Kiedy użytkownik opuszcza aktywność, system wywołuje inne metody, które przesuwają stan w dół piramidy w celu zakończenia aktywności. W niektórych przypadkach aktywność przesuwana jest tylko o kilka stopni w dół (np. kiedy użytkownik przełącza się do innej aplikacji) i może z tego miejsca powrócić na szczyt (jeśli użytkownik do niej wróci) i wznowić działanie.
O tym, które metody cyklu życia należy zaimplementować decyduje złożoność aktywności. Istotne jednak jest, aby zrozumieć je wszystkie i implementować te, które sprawią, że aplikacja będzie zachowywać się zgodnie z oczekiwaniami użytkownika. Prawidłowe zaimplementowanie metod cyklu życia aktywności gwarantuje, że aplikacja będzie zachowywać się poprawnie pod kilkoma względami, w tym:
- nie będzie ulegać awarii, kiedy użytkownik odbierze połączenie lub przełączy się do innej aplikacji w czasie korzystania z programu;
- nie będzie zużywać cennych zasobów systemowych, jeśli użytkownik będzie wykorzystywać jej funkcjonalność w ograniczonym stopniu;
- będzie zapisywać postęp użytkownika, jeśli ten zdecyduje się opuścić aplikację i do niej wrócić;
- nie będzie ulegać awarii lub tracić postępu użytkownika po obróceniu ekranu i przełączeniu się między orientacjami poziomą i pionową.
Jak dowiesz się kolejnych lekcjach, istnieje kilka sytuacji, w których aktywność przechodzi między stanami przedstawionymi na rys. 1. Niemniej jednak tylko trzy z przedstawionych stanów mogą być statyczne, co oznacza, że tylko w którymś z nich aktywność może pozostawać przez dłuższy czas.
- Wznowienie
- W tym stanie aktywność wykonywana jest na pierwszym planie i użytkownik może wchodzić z nią w interakcje. (Stan ten określany jest też czasem stanem „wykonywania”).
- Wstrzymanie
- W tym stanie aktywność jest częściowo przesłonięta przez inną aktywność znajdującą się na pierwszym planie — jest ona półprzezroczysta bądź zajmuje tylko część ekranu. Wstrzymana aktywność nie może przyjąć danych wejściowych od użytkownika ani wykonać żadnego kodu.
- Zatrzymanie
- W tym stanie aktywność jest całkowicie ukryta i pozostaje niewidoczna dla użytkownika. Można powiedzieć, że znajduje się w tle. Po zatrzymaniu aktywności, jej obiekt i wszystkie informacje na temat jej stanu, np. zmienne składowe, zostają zachowane. Wykonywanie kodu jest jednak niemożliwe.
Inne stany (utworzenie i uruchomienie) są przejściowe i system szybko przenosi się z nich do następnego stanu poprzez wywołanie metody zwrotnej następnego cyklu. Oznacza to, że po wywołaniu przez system metody onCreate()
następuje szybkie wywołanie onStart()
, które poprzedza kolejne szybkie wywołanie onResume()
.
To wszystko, jeśli chodzi o podstawy dotyczące cyklu życia aktywności. Teraz możemy przejść do omówienia konkretnych zachowań cyklu.
Określanie aktywności startowej
Po wybraniu przez użytkownika ikony aplikacji na ekranie głównym, system wywoła metodę OnCreate
odpowiadającą tej aktywności aplikacji, która została zadeklarowana jako „startowa” (lub „główna”). Aktywność ta służy jako główny punkt dostępu do interfejsu użytkownika w aplikacji.
Aktywność główną można zdefiniować w pliku manifestu, AndroidManifest.xml, który znajduje się w nadrzędnym katalogu projektu.
Należy pamiętać, aby zrobić to przy pomocy filtru intencji — <intent-filter>
— który zawiera element określający główną akcję (MAIN
) i kategorię startową (LAUNCHER
). Przykład:
<activity android:name=".MainActivity" android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
Jeśli dla żadnej aktywność nie zostanie zadeklarowana główna akcja lub kategoria startowa, ikona aplikacji nie będzie wówczas uwzględniona na znajdującej się na ekranie głównym liście aplikacji.
Tworzenie nowej instancji
Większość aplikacji zawiera kilka aktywności, dzięki którym użytkownik może wykonywać różne działania. Każda nowa instancja aktywności tworzona jest przez system poprzez wywołanie metody onCreate()
. Dzieje się tak zawsze niezależnie od tego, czy chodzi o aktywność startową utworzoną podczas uruchomienia aplikacji, czy o inną aktywność wywołaną przez system w odpowiedzi na działanie użytkownika.
Implementacja metody OnCreate()
jest niezbędna do zainicjowania wszystkich niezbędnych elementów aplikacji, co powinno nastąpić tylko raz w całym życiu aktywności. Przykładowo metoda ta powinna definiować interfejs użytkownika i ewentualnie utworzyć wystąpienia niektórych zmiennych dla atrybutów class
i scope
.
Poniższe przykłady metody onCreate()
przedstawiają fragmenty kodu, które odpowiadają za podstawowe przygotowanie aktywności, takie jak zdeklarowanie interfejsu użytkownika (zdefiniowanego w pliku XML układu), zdefiniowanie zmiennych składowych czy konfigurację elementów interfejsu.
TextView mTextView; // zmienna składowa odpowiadająca widokowi tekstu w układzie
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// określa układ interfejsu użytkownika dla danej aktywności
// plik układu zdefiniowany jest w pliku res/layout/main_activity.xml projektu
setContentView(R.layout.main_activity);
// inicjuje komponent TextView, co umożliwi jego późniejszą manipulację
mTextView = findViewById(R.id.text_message) (TextView);
// przy pomocy API paska akcji upewnij się, że aplikacja uruchomiona została na systemie Honeycomb lub nowszym
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
// upewnij się, że w przypadku głównej aktywności znajdująca się na pasku akcji ikona aplikacji
// nie zachowuje się jak przycisk
ActionBar actionBar = getActionBar();
actionBar.setHomeButtonEnabled(false);
}
}
Po wykonaniu metody onCreate()
system szybko przejdzie do wywoływania kolejno metody onStart()
i onResume()
. Aktywność nigdy nie może pozostać na dłużej w stanie utworzenia ani uruchomienia. Podczas wykonywania metody onStart()
aktywność jest wprawdzie widoczna dla użytkownika, jednak w krótkim czasie zostaje wywołana metoda onResume()
, która nadaje aktywności stan wznowienia. Ulega on zmianie dopiero wówczas, gdy użytkownik odbierze połączenie, przejdzie do innej aktywności lub wyłączy ekran urządzenia.
W kolejnych lekcjach zobaczysz, jak inne metody startowe, onStart()
i onResume()
, można wykorzystać w czasie cyklu życia do wznowienia aktywności ze stanów wstrzymania i zatrzymania.
Niszczenie aktywności
W przeciwieństwie do onCreate()
, stanowiącej pierwszą metodę wywołania zwrotnego cyklu życia, onDestroy()
jest wywołaniem ostatnim. System wykonuje tę metodę na aktywności po otrzymaniu informacji, że instancja aktywności jest całkowicie usuwana z pamięci.
W większości aplikacji metody tej nie trzeba implementować, ponieważ odniesienia do klas lokalnych są niszczone wraz z aktywnością. Aktywność powinna sama zwolnić większość zasobów podczas wywoływania metod onPause()
i onStop()
. Jeśli jednak zachowane są jakieś wątki w tle, które zostały utworzone podczas wywołania onCreate()
lub inne wykorzystywane przez dłuższy czas zasoby, niosące ze sobą ryzyko wycieku pamięci w przypadku ich niepoprawnego zamknięcia, należy je usunąć korzystając właśnie z metody onDestroy()
.
@Override
public void onDestroy() {
super.onDestroy(); // zawsze wywołuje superklasę
// zatrzymuje metodę śledzącą aktywność uruchomioną poprzez metodę onCreate()
android.os.Debug.stopMethodTracing();
}