Cykl życia aplikacji mobilnej określa, jak zachowuje się ona podczas uruchamiania, minimalizowania, powrotu z tła i zamykania. W tym artykule omówimy App Lifecycle (iOS), Activity Lifecycle (Android), Fragment Lifecycle, ViewController Lifecycle i LifecycleOwner. Zrozumienie tych procesów jest kluczowe dla zapobiegania wyciekom pamięci, utracie danych i nieprawidłowemu działaniu aplikacji. Więcej szczegółów w oficjalnej dokumentacji Android Activity Lifecycle.
Najważniejsze
Zanim przejdziemy do cyklu życia poszczególnych ekranów, ważne jest zrozumienie cyklu życia całej aplikacji. W iOS aplikacja przechodzi przez pięć stanów: Not Running (nie uruchomiona), Inactive (w tle, nie odbiera zdarzeń), Active (aktywna), Background (w tle, kod jest wykonywany) i Suspended (w tle, kod zawieszony). Te stany są zarządzane w AppDelegate przez metody applicationDidFinishLaunching, applicationDidBecomeActive, applicationWillResignActive, applicationDidEnterBackground i applicationWillTerminate.
W Android odpowiednikiem jest Application Lifecycle, śledzony przez interfejs Application.ActivityLifecycleCallbacks. Jednak Android bardziej skupia się na cyklu życia Activity — pojedynczego ekranu aplikacji. Dzieje się tak, ponieważ aplikacja Android może składać się z wielu Activity, każde z własnym cyklem.
Nowoczesne podejście w Android to użycie ProcessLifecycleOwner z biblioteki lifecycle-process. Pozwala on śledzić stan całego procesu bez przywiązywania się do konkretnej Activity. W iOS do śledzenia stanu aplikacji używa się UISceneDelegate (od iOS 13) lub AppDelegate. SceneDelegate obsługuje wiele okien (multiwindow) na iPadzie. Zrozumienie App Lifecycle jest szczególnie ważne dla IT Sectr przy tworzeniu aplikacji z synchronizacją w tle, strumieniowaniem i połączeniami VoIP.
Activity to podstawowy komponent aplikacji Android, reprezentujący jeden ekran. Activity ma jasno określony cykl życia zarządzany przez system operacyjny w odpowiedzi na działania użytkownika i zdarzenia systemowe (obrót ekranu, przychodzące połączenie, brak pamięci).
| Metoda | Opis | Co robić |
|---|---|---|
| onCreate | Wywoływana raz przy tworzeniu Activity | Inicjalizacja UI, findViewById, konfiguracja ViewModel |
| onStart | Activity staje się widoczna | Uruchom animacje, zarejestruj BroadCastReceiver |
| onResume | Activity otrzymuje fokus wejścia | Uruchom kamerę, czujniki, animacje |
| onPause | Activity traci fokus (częściowo widoczna) | Zapisz szkice, zatrzymaj animacje |
| onStop | Activity nie jest widoczna | Zwolnij zasoby, zatrzymaj aktualizacje |
| onDestroy | Activity jest niszczona | Wyczyść wszystkie referencje, anuluj subskrypcję LiveData |
| onRestart | Wywoływana przed onStart po onStop | Ponowna inicjalizacja |
Ważne: onSaveInstanceState jest wywoływana przed onStop w celu zapisania tymczasowego stanu. Przywracanie następuje w onCreate przez Bundle savedInstanceState lub przez SavedStateHandle w ViewModel. Bez prawidłowego obsłużenia cyklu życia aplikacja straci wszystkie niezapisane dane przy obrocie ekranu.
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
outState.putString("draft", draftText)
}
override fun onDestroy() {
super.onDestroy()
// Отписка от всех подписок
}
}
W Jetpack Compose cykl życia Activity pozostaje niezmieniony, ale Compose zapewnia dodatkowe narzędzia: Kompozycja świadoma cyklu życia przez LifecycleOwner, efekty LifecycleEventEffect i DisposableEffect do automatycznego czyszczenia zasobów przy zniszczeniu.
Fragment w Android żyje wewnątrz Activity i ma własny cykl życia, który częściowo pokrywa się z Activity, ale dodaje nowe metody. Fragmenty mogą być dodawane, zastępowane, usuwane bez niszczenia Activity, co czyni je bardziej elastycznymi, ale także bardziej złożonymi.
Kluczowe metody Fragment Lifecycle: onAttach — Fragment dołączony do Activity (pierwsze wywołanie); onCreate — inicjalizacja danych; onCreateView — tworzenie View; onViewCreated — View utworzone, można konfigurować UI; onStart — Fragment widoczny; onResume — Fragment w fokusie; onPause — Fragment traci fokus; onStop — Fragment niewidoczny; onDestroyView — View niszczone; onDestroy — Fragment niszczony; onDetach — Fragment odłączony od Activity.
Kluczowa różnica od Activity: onCreateView i onDestroyView mogą być wywoływane wielokrotnie (np. przy przełączaniu TabLayout), podczas gdy onCreate jest wywoływany raz. W związku z tym inicjalizacja View powinna być wykonana w onViewCreated, a nie w onCreateView. Zasoby związane z View (np. adaptery RecyclerView) powinny być czyszczone w onDestroyView.
UIViewController to klasa bazowa do zarządzania ekranami w iOS. Jego cykl życia składa się z sekwencji metod, które UIKit wywołuje automatycznie. Zrozumienie tego cyklu jest kluczowe dla prawidłowej inicjalizacji UI, zarządzania danymi i pamięcią.
| Metoda | Kiedy wywoływana | Typowe użycie |
|---|---|---|
| loadView | Gdy View Controller ładuje swoją hierarchię View | Niestandardowa inicjalizacja bez storyboard |
| viewDidLoad | Po załadowaniu View do pamięci (raz) | Konfiguracja UI, załadowanie początkowych danych |
| viewWillAppear | Przed pojawieniem się View na ekranie | Aktualizacja danych, subskrypcja powiadomień |
| viewDidAppear | Po pojawieniu się View na ekranie | Uruchomienie animacji, uruchomienie animacji śledzenia |
| viewWillDisappear | Przed zniknięciem View z ekranu | Zapisanie stanu, anulowanie subskrypcji powiadomień |
| viewDidDisappear | Po zniknięciu View z ekranu | Zatrzymanie animacji, zwolnienie zasobów |
| dealloc | Gdy View Controller jest niszczony | Zwolnienie wszystkich zasobów |
Ważne: viewDidLoad jest wywoływany tylko raz w ciągu życia View Controller. Do aktualizacji danych przy każdym pojawieniu się używaj viewWillAppear. Jeśli subskrybujesz NotificationCenter w viewWillAppear, pamiętaj o anulowaniu subskrypcji w viewDidDisappear, aby uniknąć wycieków pamięci.
SwiftUI zarządza cyklem życia View przez struktury View. Zamiast metod callback, SwiftUI używa modyfikatorów onAppear i onDisappear. Dla globalnych stanów aplikacji używany jest App Lifecycle przez protokoły App i Scene. SwiftUI automatycznie zarządza tworzeniem i niszczeniem View na podstawie stanu, co upraszcza tworzenie, ale wymaga zrozumienia tożsamości i czasu życia View.
struct ContentView: View {
var body: some View {
Text("Hello")
.onAppear {
print("View появилась")
}
.onDisappear {
print("View исчезла")
}
}
}
LifecycleOwner to interfejs z Android Architecture Components, który oznacza obiekt mający cykl życia (Activity, Fragment). LifecycleObserver to interfejs umożliwiający obiektowi subskrybowanie zdarzeń LifecycleOwner. Razem stanowią podstawę reaktywnego zarządzania cyklem życia w nowoczesnym tworzeniu aplikacji Android.
Zamiast jawnego wywoływania metod w onStart/onStop, zaleca się używanie DefaultLifecycleObserver (zamiennika przestarzałego LifecycleObserver z adnotacjami @OnLifecycleEvent). Jest to podejście promowane przez Google dla ViewModel i innych komponentów, które muszą reagować na cykl życia bez posiadania bezpośrednich referencji do Activity lub Fragment.
class MyObserver : DefaultLifecycleObserver {
override fun onStart(owner: LifecycleOwner) {
// Подписка на обновления
}
override fun onStop(owner: LifecycleOwner) {
// Отписка
}
}
W IT Sectr używamy LifecycleOwner we wszystkich projektach Android. ViewModel subskrybuje LifecycleOwner Activity przez viewModelScope i lifecycleScope, gwarantując automatyczne anulowanie korutyn przy zniszczeniu Activity. Zapobiega to wyciekom pamięci i sprawia, że kod jest czystszy i bezpieczniejszy.
Często zadawane pytania
Activity przechodzi przez sześć stanów: Created (onCreate), Started (onStart), Resumed (onResume), Paused (onPause), Stopped (onStop), Destroyed (onDestroy).
Kolejność: loadView → viewDidLoad → viewWillAppear → viewDidAppear → viewWillDisappear → viewDidDisappear. viewDidLoad jest wywoływany raz.
LifecycleOwner to komponent Android Architecture Components, który posiada cykl życia Activity lub Fragment. Umożliwia subskrybowanie zdarzeń przez LifecycleObserver.
Aplikacja iOS przechodzi przez pięć stanów: Not Running, Inactive, Active, Background, Suspended. Przejścia są zarządzane przez UIApplicationDelegate.
Saved State to mechanizm Android do zachowywania stanu Activity/Fragment przy obrocie ekranu lub odtworzeniu procesu. Używa onSaveInstanceState i SavedStateHandle.
Podsumowanie
Opracujemy aplikację mobilną pod klucz
IT Sectr tworzy aplikacje na iOS i Androida dla startupów i firm od 2017 roku. Doradzimy Ci i zaproponujemy najlepsze rozwiązanie.