onStart — este metoda ciclului de viață Android care este apelată când Activity sau Fragment devin vizibile pentru utilizator. În acest moment ecranul apare pe display-ul dispozitivului, dar încă nu poate interacționa cu utilizatorul — focalizarea de intrare este absentă până la apelarea onResume. Metoda onStart este ideală pentru înregistrarea listener-ilor sistemici, conectarea la servicii de geolocalizare și pornirea animațiilor care trebuie să funcționeze cât timp componentul este vizibil pe ecran. Mai multe despre ciclul de viață complet al Activity citiți în articolul Activity Lifecycle.
Principalul
onStart — a doua metodă a ciclului de viață Activity, care este apelată de sistem după onCreate (sau după onRestart la revenirea din starea oprită). În momentul apelării onStart, Activity sau Fragment devin vizibile pe ecran. Utilizatorul vede interfața, dar ecranul nu este încă pregătit pentru interacțiune — focalizarea de intrare va apărea doar după onResume.
Metoda onStart face parte din „durata de viață vizibilă" (visible lifetime) a Activity — intervalul dintre onStart și onStop. În această perioadă Activity poate fi parțial acoperită de alte ferestre (de exemplu, de o Activity transparentă sau o fereastră de dialog), dar UI-ul său rămâne vizibil. Aceasta deosebește durata de viață vizibilă de „durata de viață în prim-plan" (onResume — onPause), când Activity are focalizare completă de intrare.
Înțelegerea acestei ierarhii pe trei niveluri este critic de importantă pentru distribuirea corectă a codului. onCreate — inițializare unică, onStart — conectarea resurselor vizibile, onResume — acces monopol la resurse exclusive. Dezvoltatorul care confundă aceste niveluri riscă să creeze scurgeri de memorie sau comportament incorect al aplicației la comutarea între ecrane.
În Activity, metoda onStart este apelată de fiecare dată când ecranul apare pe display — atât la prima lansare (după onCreate), cât și la revenirea din modul de fundal (după onRestart). Spre deosebire de onCreate, onStart poate fi apelat de mai multe ori în timpul vieții instanței Activity, de aceea aici se plasează codul care trebuie executat de fiecare dată când ecranul apare.
class DashboardActivity : AppCompatActivity() {
private val connectivityReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
val isConnected = ... // verificare 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()
}
}
Regula cheie: toate resursele conectate în onStart trebuie eliberate în onStop. Aceasta garantează că atunci când Activity este ascunsă de pe ecran, nu consumă baterie, nu ascultă evenimente sistemice și nu ocupă memorie. Android Studio conține reguli lint care avertizează despre înregistrarea BroadcastReceiver fără dezabonarea corespunzătoare.
onStart în Fragment este strâns legat de ciclul de viață al Activity-container. Fragmentul primește apelul onStart după ce Activity-ul în care se află a primit onStart. Totuși, dacă Fragmentul a fost adăugat în modul întârziat (FragmentTransaction.commit() fără addToBackStack), onStart poate fi apelat cu întârziere.
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()
}
}
Specificul Fragment.onStart: dacă Fragmentul se află într-un ViewPager cu offscreenPageLimit = 1, fragmentele învecinate vor primi de asemenea onStart înainte de a deveni vizibile. Aceasta poate duce la înregistrarea prematură a listener-ilor. Pentru astfel de cazuri se utilizează metoda setUserVisibleHint() sau verificarea isVisible în interiorul onStart pentru a înregistra listener-i doar pentru fragmentele efectiv vizibile.
Diferența principală dintre onStart și onResume — nivelul de activitate a ecranului. onStart semnalează că Activity este vizibilă pe ecran, dar nu neapărat se află în prim-plan. onResume semnalează că Activity se află în prim-plan și are focalizare de intrare. Diferența este demonstrată prin exemplul ferestrei de dialog: când deasupra Activity apare un Dialog, Activity pierde onResume (se apelează onPause), dar rămâne vizibilă — onStart/onStop nu sunt apelate.
Tabelul diferențelor arată clar în ce scenarii este apelată fiecare metodă:
| Scenariu | onStart | onResume |
|---|---|---|
| Lansarea aplicației | Apelat | Apelat |
| Deasupra Activity este deschis Dialog | Nu este apelat | onPause (pierdere focalizare) |
| Apăsarea butonului „Acasă" | onStop (ascuns) | onPause → onStop |
| Revenirea din „Recent" | onStart (vizibil) | onResume (focalizare) |
| Rotirea ecranului | onCreate → onStart | → onResume |
| Apel primit | onStop (ascuns) | onPause → onStop |
Acest tabel ajută dezvoltatorul să decidă în ce metodă să plaseze codul concret. De exemplu, dacă aplicația trebuie să întrerupă redarea video la orice acoperire a ecranului (chiar și cu un dialog), codul se plasează în onPause. Dacă video-ul trebuie să se oprească doar la ascunderea completă a ecranului — codul se plasează în onStop.
onStart — locul optim pentru înregistrarea listener-ilor care trebuie să funcționeze doar cât timp Activity este vizibilă pe ecran. Aceasta privește trei tipuri principale de componente sistemice: BroadcastReceiver pentru evenimente sistemice, LocationListener pentru geolocalizare și SensorListener pentru senzorii dispozitivului.
BroadcastReceiver se înregistrează dinamic prin Context.registerReceiver() în onStart și se dezabonează în onStop prin unregisterReceiver(). Înregistrarea dinamică este preferabilă celei statice (în manifest), deoarece limitează durata de viață a receptorului la perioada de vizibilitate a Activity — aplicația nu se trezește din cauza mesajelor broadcast sistemice când Activity este ascunsă.
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()
}
Geolocalizarea și senzorii — operații consumatoare de resurse. Solicitarea actualizărilor GPS în onStart și anularea în onStop garantează că aplicația nu consumă baterie când ecranul este ascuns. Pentru ajustarea fină se utilizează requestLocationUpdates cu interval și distanță minimă — de exemplu, 10 secunde și 10 metri, ceea ce oferă un echilibru optim între precizie și consumul de energie.
Pornirea animațiilor în onStart, nu în onCreate, garantează că animația pornește de fiecare dată când ecranul apare. Dacă porniți animația în onCreate, va funcționa doar la prima creare a Activity, dar nu la revenirea din modul de fundal. onStart este apelat de fiecare dată când Activity devine vizibilă, ceea ce îl face locul ideal pentru pornirea animațiilor ciclice și a tranzițiilor.
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()
}
Pentru animațiile care utilizează ObjectAnimator sau ValueAnimator, este important să se apeleze cancel() în onStop. Dacă animația continuă să funcționeze după ascunderea Activity, consumă inutil resurse GPU și CPU, ceea ce reduce performanța dispozitivului și accelerează descărcarea bateriei. Android Studio Profiler (graficul GPU) permite urmărirea animațiilor active și detectarea scurgerilor.
Regula perechii onStart/onStop se aplică și lucrului cu camera pentru previzualizare (CameraX). Deschiderea camerei în onStart și închiderea în onStop garantează că camera nu este blocată pentru alte aplicații când aplicația dvs. nu este vizibilă pe ecran. Încălcarea acestei reguli este una dintre cauzele frecvente ale recenziilor negative în Google Play.
Întrebări frecvente
onStart — pentru listener-i care trebuie să funcționeze cât timp ecranul este vizibil (BroadcastReceiver, LocationListener, SensorListener). onResume — pentru resurse care necesită acces monopol (cameră, captură video, recunoaștere vocală). Listener-ii evenimentelor sistemice nu necesită acces monopol și pot funcționa la acoperire parțială — se înregistrează în onStart. Camera trebuie să fie activă doar la focalizare completă — se deschide în onResume.
onStart este întotdeauna apelat dacă Activity trece în stare vizibilă. Singurul scenariu fără onStart — Activity este creată și imediat terminată (de exemplu, din cauza unei erori în onCreate). În acest caz, după onCreate urmează direct onDestroy. Dar acesta este un scenariu de urgență care nu ar trebui să apară într-un cod scris corect.
Da, onStart poate să nu primească onResume dacă deasupra Activity se deschide imediat o altă Activity sau o fereastră transparentă. De exemplu, dacă după onCreate se lansează un ecran de autentificare (Activity A → Activity B), în Activity A onStart este apelat, dar onResume nu — primește direct onPause → onStop la acoperirea cu ecranul B.
onStart poate fi apelat de mai multe ori în timpul vieții instanței Activity. De fiecare dată când Activity trece din starea ascunsă (onStop) în starea vizibilă, se apelează onStart. În practică, la utilizarea activă a aplicației, onStart poate fi apelat de zeci sau sute de ori într-o sesiune.
Încărcarea datelor în onStart este justificată dacă datele trebuie actualizate de fiecare dată când ecranul apare. De exemplu, un flux de știri sau o listă de notificări. Dar încărcarea trebuie să fie asincronă — prin corutine cu lifecycleScope, pentru a nu bloca firul UI. Pentru datele care nu se modifică între aparițiile ecranului, este suficient să le încărcați o dată în onCreate.
Rezumat
Vom dezvolta o aplicație mobilă la cheie
IT Sectr creează aplicații iOS și Android pentru startup-uri și afaceri din 2017. Vă vom consilia și vă vom propune cea mai bună soluție.
Citiți și