onStart: istota, widoczność Activity na ekranie Android

Autor: IT Sectr Opublikowano: 2026-03-04 Czas czytania: 9 min

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 — wywoływany, gdy Activity lub Fragment staje się widoczny na ekranie; poprzedza onResume
  • Rejestracja słuchaczy — BroadcastReceiver, LocationListener, SensorListener rejestrują się w onStart i wypisują w onStop
  • Animacje — uruchamianie animacji, które powinny działać, dopóki ekran jest widoczny; wstrzymanie w onStop
  • Bound-usługi — podłączanie do klient-serwerowych usług przez bindService w onStart, odłączanie w onStop
  • onStart vs onResume — onStart = widoczność, onResume = fokus + interakcja; różne poziomy aktywności ekranu
  • Fragment.onStart — wywoływany po Activity.onStart, gdy Fragment staje się widoczny w kontenerze
  • Para onStart/onStop — zasoby podłączone w onStart należy koniecznie zwolnić w onStop, aby zapobiec wyciekom

Istota metody onStart w Android

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.

onStart w Activity

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.

kotlin
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

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.

kotlin
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.

Różnica między onStart a onResume

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:

ScenariuszonStartonResume
Uruchomienie aplikacjiWywoływaneWywoływane
Na Activity otwarto DialogNie wywoływaneonPause (utrata fokusa)
Naciśnięcie przycisku „Home"onStop (ukryte)onPause → onStop
Powrót z „Ostatnich"onStart (widoczne)onResume (fokus)
Obrót ekranuonCreate → onStart→ onResume
Połączenie przychodząceonStop (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.

Rejestracja słuchaczy i usług

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 w onStart

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.

kotlin
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()
}

LocationListener i SensorListener

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.

Animacje i onStart

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ść.

kotlin
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

Jaka jest różnica między onStart a onResume przy rejestracji słuchaczy?

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.

Dlaczego onStart może nie być wywołane?

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.

Czy onStart może być wywołane bez onResume?

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.

Ile razy może być wywołane onStart?

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.

Czy warto ładować dane w onStart?

Ł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

  • onStart — metoda widzialnego okresu życia; wywoływana, gdy Activity lub Fragment pojawiają się na ekranie
  • Rejestracja w onStart — BroadcastReceiver, LocationListener, SensorListener rejestrują w onStart i wypisują w onStop
  • onStart vs onResume — onStart = widoczność, onResume = fokus wejścia; różne poziomy dla różnych typów zasobów
  • Animacje — uruchamianie cyklicznych animacji w onStart, zatrzymywanie w onStop; zapobiega wyciekom zasobów GPU
  • Fragment.onStart — powiązany z Activity.onStart; w ViewPager wywoływany dla sąsiednich fragmentów z wyprzedzeniem
  • Zasada par — wszystkie zasoby onStart muszą być zwolnione w onStop, w przeciwnym razie wyciek pamięci i baterii
  • Ładowanie danych — w onStart ładuje się dane, które powinny być aktualizowane przy każdym pojawieniu się ekranu

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.

Omów projekt

Przeczytaj również