onStart — to metoda cyklu życia Android, która jest wywoływana, gdy Activity lub Fragment stają się widoczne dla użytkownika. W tym momencie ekran pojawia się na wyświetlaczu urządzenia, ale nie może jeszcze w pełni interakcjonować z użytkownikiem — fokus wejścia jest nieobecny do momentu wywołania onResume. Metoda onStart jest idealna do rejestracji systemowych słuchaczy, podłączania do usług geolokalizacji i uruchamiania animacji, które powinny działać, dopóki komponent jest widoczny na ekranie. Więcej o pełnym cyklu życia Activity przeczytasz w artykule Activity Lifecycle.
Najważniejsze
onStart — druga metoda cyklu życia Activity, wywoływana przez system po onCreate (lub po onRestart przy powrocie ze stanu zatrzymanego). W momencie wywołania onStart Activity lub Fragment stają się widoczne na ekranie. Użytkownik widzi interfejs, ale ekran nie jest jeszcze gotowy do interakcji — fokus wejścia pojawi się dopiero po onResume.
Metoda onStart wchodzi w skład „widzialnego okresu życia" (visible lifetime) Activity — przedziału między onStart a onStop. W tym okresie Activity może być częściowo zasłonięta przez inne okna (na przykład przez przezroczyste Activity lub okno dialogowe), ale jej UI pozostaje widoczne. To odróżnia widzialny okres życia od „okresu życia na pierwszym planie" (onResume — onPause), gdy Activity ma pełny fokus wejścia.
Zrozumienie tej trójpoziomowej hierarchii jest krytycznie ważne dla prawidłowego rozłożenia kodu. onCreate — jednorazowa inicjalizacja, onStart — podłączanie widocznych zasobów, onResume — wyłączny dostęp do ekskluzywnych zasobów. Deweloper, który myli te poziomy, ryzykuje stworzenie wycieków pamięci lub nieprawidłowe zachowanie aplikacji przy przełączaniu między ekranami.
W Activity metoda onStart jest wywoływana za każdym razem, gdy ekran pojawia się na wyświetlaczu — zarówno przy pierwszym uruchomieniu (po onCreate), jak i przy powrocie z trybu tła (po onRestart). W przeciwieństwie do onCreate, onStart może być wywoływany wielokrotnie w ciągu życia instancji Activity, dlatego umieszcza się tu kod, który powinien być wykonywany za każdym razem przy pojawieniu się ekranu.
class DashboardActivity : AppCompatActivity() {
private val connectivityReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
val isConnected = ... // sprawdzenie ConnectivityManager
binding?.statusIndicator?.setColor(
if (isConnected) Color.GREEN else Color.RED
)
}
}
override fun onStart() {
super.onStart()
registerReceiver(
connectivityReceiver,
IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION)
)
SensorManager.getInstance().registerStepCounter()
}
override fun onStop() {
unregisterReceiver(connectivityReceiver)
SensorManager.getInstance().unregisterStepCounter()
super.onStop()
}
}
Kluczowa zasada: wszystkie zasoby podłączone w onStart muszą zostać zwolnione w onStop. Gwarantuje to, że gdy Activity jest ukryte z ekranu, nie pobiera baterii, nie nasłuchuje zdarzeń systemowych i nie zajmuje pamięci. Android Studio zawiera reguły lint ostrzegające przed rejestracją BroadcastReceiver bez odpowiedniego wypisania się.
onStart we Fragment jest ściśle powiązany z cyklem życia Activity-kontenera. Fragment otrzymuje wywołanie onStart po tym, jak Activity, w którym się znajduje, otrzymało onStart. Jednak jeśli Fragment został dodany w trybie opóźnionym (FragmentTransaction.commit() bez addToBackStack), onStart może być wywołany z opóźnieniem.
class MapFragment : Fragment() {
private var mapView: MapView? = null
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
mapView = MapView(requireContext())
return mapView!!
}
override fun onStart() {
super.onStart()
mapView?.onStart()
LocationService.connect(requireContext())
}
override fun onStop() {
mapView?.onStop()
LocationService.disconnect()
super.onStop()
}
}
Specyfika Fragment.onStart: jeśli Fragment znajduje się w ViewPager z offscreenPageLimit = 1, sąsiednie fragmenty również otrzymają onStart zanim staną się widoczne. Może to prowadzić do przedwczesnej rejestracji słuchaczy. W takich przypadkach stosuje się metodę setUserVisibleHint() lub sprawdzenie isVisible wewnątrz onStart, aby rejestrować słuchaczy tylko dla rzeczywiście widocznych fragmentów.
Główna różnica między onStart a onResume — poziom aktywności ekranu. onStart sygnalizuje, że Activity jest widoczne na ekranie, ale niekoniecznie znajduje się na pierwszym planie. onResume sygnalizuje, że Activity znajduje się na pierwszym planie i ma fokus wejścia. Różnicę ilustruje przykład okna dialogowego: gdy na Activity pojawia się Dialog, Activity traci onResume (wywoływane jest onPause), ale pozostaje widoczne — onStart/onStop nie są wywoływane.
Tabela różnic wyraźnie pokazuje, w jakich scenariuszach wywoływana jest każda metoda:
| Scenariusz | onStart | onResume |
|---|---|---|
| Uruchomienie aplikacji | Wywoływane | Wywoływane |
| Na Activity otwarto Dialog | Nie wywoływane | onPause (utrata fokusa) |
| Naciśnięcie przycisku „Home" | onStop (ukryte) | onPause → onStop |
| Powrót z „Ostatnich" | onStart (widoczne) | onResume (fokus) |
| Obrót ekranu | onCreate → onStart | → onResume |
| Połączenie przychodzące | onStop (ukryte) | onPause → onStop |
Ta tabela pomaga deweloperowi zdecydować, w której metodzie umieścić konkretny kod. Na przykład, jeśli aplikacja musi wstrzymywać odtwarzanie wideo przy każdym zasłonięciu ekranu (nawet dialogiem), kod umieszcza się w onPause. Jeśli wideo powinno się zatrzymywać tylko przy całkowitym ukryciu ekranu — kod umieszcza się w onStop.
onStart — optymalne miejsce do rejestracji słuchaczy, które powinny działać tylko gdy Activity jest widoczne na ekranie. Dotyczy to trzech głównych typów komponentów systemowych: BroadcastReceiver do zdarzeń systemowych, LocationListener do geolokalizacji i SensorListener do czujników urządzenia.
BroadcastReceiver rejestruje się dynamicznie przez Context.registerReceiver() w onStart i wypisuje w onStop przez unregisterReceiver(). Rejestracja dynamiczna jest preferowana nad statyczną (w manifeście), ponieważ ogranicza czas życia odbiornika do okresu widoczności Activity — aplikacja nie budzi się z powodu systemowych broadcast-communikatów, gdy Activity jest ukryte.
private val batteryReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent) {
val level = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1)
binding?.batteryText?.text = "$level%"
}
}
override fun onStart() {
super.onStart()
registerReceiver(batteryReceiver, IntentFilter(Intent.ACTION_BATTERY_CHANGED))
}
override fun onStop() {
unregisterReceiver(batteryReceiver)
super.onStop()
}
Geolokalizacja i czujniki — operacje zasobożerne. Żądanie aktualizacji GPS w onStart i anulowanie w onStop gwarantuje, że aplikacja nie zużywa baterii, gdy ekran jest ukryty. Do precyzyjnego dostrojenia używa się requestLocationUpdates z minimalnym interwałem i dystansem — na przykład 10 sekund i 10 metrów, co daje optymalną równowagę między dokładnością a zużyciem energii.
Uruchamianie animacji w onStart, a nie w onCreate, gwarantuje, że animacja startuje za każdym razem przy pojawieniu się ekranu. Jeśli uruchomisz animację w onCreate, zadziała ona tylko przy pierwszym utworzeniu Activity, ale nie przy powrocie z trybu tła. onStart jest wywoływany za każdym razem, gdy Activity staje się widoczne, co czyni go idealnym miejscem do uruchamiania cyklicznych animacji i przejść.
private lateinit var pulseAnimator: ValueAnimator
override fun onStart() {
super.onStart()
pulseAnimator.start()
binding?.loadingIndicator?.animate()?.alpha(1f)?.start()
}
override fun onStop() {
pulseAnimator.cancel()
binding?.loadingIndicator?.animate()?.cancel()
super.onStop()
}
Dla animacji używających ObjectAnimator lub ValueAnimator ważne jest wywołanie cancel() w onStop. Jeśli animacja kontynuuje działanie po ukryciu Activity, bezcelowo zużywa zasoby GPU i CPU, co obniża wydajność urządzenia i przyspiesza rozładowanie baterii. Android Studio Profiler (wykres GPU) pozwala śledzić aktywne animacje i wykrywać wycieki.
Zasada pary onStart/onStop ma zastosowanie również do pracy z kamerą do podglądu (CameraX). Otwarcie kamery w onStart i zamknięcie w onStop gwarantuje, że kamera nie jest zablokowana dla innych aplikacji, gdy twoja aplikacja nie jest widoczna na ekranie. Naruszenie tej zasady to jedna z częstych przyczyn negatywnych recenzji w Google Play.
Często zadawane pytania
onStart — dla słuchaczy, które powinny działać, dopóki ekran jest widoczny (BroadcastReceiver, LocationListener, SensorListener). onResume — dla zasobów wymagających wyłącznego dostępu (kamera, przechwytywanie wideo, rozpoznawanie mowy). Słuchacze zdarzeń systemowych nie wymagają wyłącznego dostępu i mogą działać przy częściowym zasłonięciu — rejestruje się je w onStart. Kamera powinna być aktywna tylko przy pełnym fokusie — otwiera się ją w onResume.
onStart jest zawsze wywoływane, jeśli Activity przechodzi w stan widoczny. Jedyny scenariusz bez onStart — Activity jest tworzone i natychmiast kończone (na przykład z powodu błędu w onCreate). W tym przypadku po onCreate następuje bezpośrednio onDestroy. Jest to jednak scenariusz awaryjny, który nie powinien występować w poprawnie napisanym kodzie.
Tak, onStart może nie otrzymać onResume, jeśli na Activity natychmiast otwiera się inne Activity lub przezroczyste okno. Na przykład, jeśli po onCreate uruchamiany jest ekran autoryzacji (Activity A → Activity B), w Activity A onStart jest wywoływane, ale onResume nie — otrzymuje ono bezpośrednio onPause → onStop przy zasłonięciu ekranem B.
onStart może być wywoływane wielokrotnie w ciągu życia instancji Activity. Za każdym razem, gdy Activity przechodzi z ukrytego stanu (onStop) w widoczny, wywoływane jest onStart. W praktyce przy aktywnym użytkowaniu aplikacji onStart może być wywoływane dziesiątki lub setki razy w trakcie sesji.
Ładowanie danych w onStart jest uzasadnione, jeśli dane powinny być aktualizowane za każdym razem przy pojawieniu się ekranu. Na przykład, kanał wiadomości lub lista powiadomień. Jednak ładowanie powinno być asynchroniczne — przez korutyny z lifecycleScope, aby nie blokować wątku UI. Dla danych, które nie zmieniają się między pojawieniami ekranu, wystarczy załadować je raz w onCreate.
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.
Przeczytaj również