onCreate — este prima și singura metodă obligatorie a ciclului de viață al Activity și Fragment în Android. Sistemul o apelează o dată la crearea componentului, transmițând parametrul Bundle cu starea salvată anterior. În interiorul onCreate, dezvoltatorul inițializează interfața utilizatorului, leagă elementele View, configurează gestionarii de evenimente și restaurează datele din savedInstanceState. Fără o implementare corectă a onCreate, nicio aplicație Android nu poate fi lansată — este punctul de intrare pentru fiecare ecran. Despre ciclul de viață general al Activity citiți în articolul Activity Lifecycle.
Principalele puncte
onCreate — o metodă de callback pe care Android o apelează la crearea unei noi instanțe de Activity sau Fragment. Acesta este primul punct de intrare în codul ecranului utilizatorului: înainte de apelarea onCreate, niciun cod al utilizatorului nu este executat. Sistemul transmite metodei parametrul Bundle, care fie conține datele salvate anterior (la recreare), fie este null (la prima lansare).
Metoda onCreate este definită în clasa android.app.Activity și în clasa androidx.fragment.app.Fragment. Ambele variante îndeplinesc sarcini similare: inițializarea componentului, configurarea UI și restaurarea stării. Cu toate acestea, implementarea specifică diferă — Activity folosește setContentView pentru încărcarea aspectului, iar Fragment returnează View prin onCreateView. Dezvoltatorul este obligat să suprascrie cel puțin onCreate în Activity — fără aceasta, Android nu poate afișa ecranul.
onCreate este apelat strict o dată pe întregul ciclu de viață al instanței Activity. Chiar și la rotirea ecranului, noua instanță Activity primește un nou apel onCreate cu Bundle de la instanța anterioară. Această proprietate face din onCreate locul ideal pentru inițializarea unică: încărcarea datelor, crearea adaptoarelor, configurarea componentelor DI prin Dagger sau Hilt.
În Activity, metoda onCreate îndeplinește patru sarcini cheie: încărcarea aspectului layout, inițializarea elementelor View, restaurarea stării din Bundle și configurarea gestionarilor primari de evenimente. Codul minim obligatoriu în onCreate — apelul super.onCreate(savedInstanceState) și setContentView(R.layout.activity_main).
class MainActivity : AppCompatActivity() {
private var binding: ActivityMainBinding? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// ViewBinding — înlocuitor modern pentru findViewById
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding?.root)
// Inițializarea cu ajutorul binding
binding?.apply {
welcomeText.text = getString(R.string.welcome)
startButton.setOnClickListener { startGame() }
}
// Restaurarea stării
if (savedInstanceState != null) {
score = savedInstanceState.getInt("score", 0)
binding?.scoreText?.text = score.toString()
}
}
}
Practica modernă — utilizarea ViewBinding în loc de findViewById. ViewBinding generează clasa ActivityMainBinding în faza de compilare, ceea ce elimină erorile cu ID-uri incorecte și reduce volumul de cod șablon. Google recomandă ViewBinding ca modalitate standard de acces la View în Activity și Fragment începând cu Android Studio 3.6.
Ordinea acțiunilor în onCreate trebuie să fie strictă: mai întâi super, apoi setContentView, după care tot restul. Apelarea findViewById înainte de setContentView returnează null — aspectul nu a fost încă încărcat, iar elementele View nu există în ierarhie. Aceasta este una dintre cele mai frecvente greșeli ale dezvoltatorilor Android începători.
onCreate în Fragment diferă de Activity: aici nu se apelează setContentView, ci se execută doar inițializarea datelor nelegate de UI. Fragment împarte crearea componentului și crearea View-ului în două metode separate: onCreate (apelată o dată) și onCreateView (apelată de fiecare dată la crearea sau recrearea View-ului).
class UserListFragment : Fragment() {
private lateinit var viewModel: UserViewModel
private var binding: FragmentUserListBinding? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// Inițializarea ViewModel — va supraviețui recreării View
viewModel = ViewModelProvider(this)[UserViewModel::class.java]
// Argumente din FragmentManager
arguments?.let {
viewModel.loadUser(it.getString("user_id") ?: "")
}
// Salvarea la rotire
retainInstance = true
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
binding = FragmentUserListBinding.inflate(inflater, container, false)
return binding!!.root
}
}
Diferența cheie între onCreate din Activity și Fragment: onCreate în Fragment nu trebuie să conțină cod legat de View, deoarece View poate fi distrus și recreat (de exemplu, la comutarea filelor ViewPager), iar onCreate este apelat doar o dată. Încărcarea datelor, configurarea ViewModel și inițializarea adaptoarelor — sarcini ale onCreate, iar legarea View-ului — sarcina onViewCreated.
Parametrul savedInstanceState în onCreate — este mecanismul de salvare și restaurare a stării temporare a Activity sau Fragment. Când sistemul distruge Activity (rotirea ecranului, lipsă de memorie), apelează onSaveInstanceState(), în care dezvoltatorul plasează o pereche cheie-valoare în Bundle. La crearea noii instanțe, acest Bundle este returnat în onCreate.
Bundle suportă următoarele tipuri de date: String, Integer, Boolean, Long, Float, Double, array-urile lor, precum și obiecte Parcelable și Serializable. Pentru obiecte complexe se folosește Parcelable — un mecanism de serializare mai performant, specific Android. Dimensiunea Bundle este limitată la aproximativ 500 KB — depășirea limitei provoacă excepția TransactionTooLargeException.
companion object {
private const val KEY_USER_NAME = "user_name"
private const val KEY_SCORE = "score"
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_game)
if (savedInstanceState != null) {
userName = savedInstanceState.getString(KEY_USER_NAME) ?: ""
currentScore = savedInstanceState.getInt(KEY_SCORE)
}
}
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
outState.putString(KEY_USER_NAME, userName)
outState.putInt(KEY_SCORE, currentScore)
}
Este important de înțeles: onSaveInstanceState nu este apelat când utilizatorul închide explicit Activity prin finish() sau prin butonul „Înapoi". Sistemul consideră că în acest caz utilizatorul încheie conștient lucrul și salvarea stării nu este necesară. Prin urmare, nu trebuie să vă bazați exclusiv pe savedInstanceState pentru stocarea pe termen lung a datelor — utilizați Room, DataStore sau SharedPreferences.
onCreate se execută în firul principal (UI), iar sistemul așteaptă finalizarea sa înainte de a afișa Activity pe ecran. Dacă onCreate durează mai mult de 5 secunde, sistemul afișează o fereastră de dialog ANR (Application Not Responding) și propune utilizatorului închiderea aplicației. Operațiile lungi, cum ar fi încărcarea datelor din rețea sau citirea din baza de date, trebuie mutate în firul de fundal.
Conform recomandărilor Google Android Performance (2025), onCreate trebuie să se finalizeze în mai puțin de 1 secundă pe dispozitivele de segment mediu. Pentru aceasta, trebuie să: utilizați inițializarea lentă (delegat lazy în Kotlin), amânați încărcarea datelor grele în onResume sau prin corutine, aplicați ViewStub pentru componentele UI rar utilizate, profilați timpul de pornire prin Android Vitals.
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// Inițializare lentă — obiectul este creat doar la prima accesare
val heavyData by lazy {
HeavyDataLoader.load()
}
// Încărcarea datelor în firul de fundal prin lifecycleScope
lifecycleScope.launch(Dispatchers.IO) {
val users = userDao.getAllUsers()
withContext(Dispatchers.Main) {
adapter.submitList(users)
}
}
}
Instrumente de profilare: Android Studio Profiler (fila CPU) arată timpul exact de execuție al fiecărei metode. În Android Vitals (consola Google Play) puteți urmări metrica „Timpul de pornire la rece" — dacă onCreate al Activity dvs. depășește 500 ms, consola îl marchează ca problemă de performanță. Noi la IT Sectr folosim teste Macrobenchmark pentru controlul automat al timpului de pornire al fiecărei Activity în pipeline-ul CI.
ViewModel — cea mai bună modalitate de inițializare a datelor în onCreate care trebuie să supraviețuiască rotației ecranului. ViewModel este creat în onCreate prin ViewModelProvider și se salvează automat la modificarea configurației. Când Activity este recreată după rotire, ViewModel rămâne în memorie, iar onCreate primește același ViewModel fără pierdere de date.
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_profile)
// ViewModel este creat o dată și supraviețuiește modificărilor de configurare
val viewModel: ProfileViewModel =
ViewModelProvider(this)[ProfileViewModel::class.java]
// Observarea LiveData — UI se actualizează automat la modificarea datelor
viewModel.user.observe(this) { user ->
binding?.userName?.text = user.name
binding?.userEmail?.text = user.email
}
// Încărcarea datelor dacă ViewModel a fost abia creat
if (savedInstanceState == null) {
viewModel.loadProfile(userId)
}
}
Combinația ViewModel + LiveData/StateFlow rezolvă problema rotației ecranului fără salvare manuală în Bundle. ViewModel stochează datele în memorie, LiveData reabonează automat Activity la recreare, iar StateFlow (din Kotlin Coroutines) adaugă reactivitate cu suport pentru corutine. Aceasta este arhitectura standard recomandată de Google în ghidul Guide to App Architecture.
Chiar și dezvoltatorii experimentați fac greșeli tipice în onCreate. Să examinăm cinci dintre cele mai frecvente probleme și metode de evitare.
Cea mai frecventă greșeală — încercarea de a găsi View prin findViewById înainte de apelarea setContentView. Toate elementele View sunt create în momentul inflatării aspectului, astfel că orice referire la findViewById înainte de setContentView returnează null și provoacă NullPointerException la încercarea de a utiliza View. Soluție: ordine strictă — mai întâi super, apoi setContentView, după care findViewById sau ViewBinding.
Încărcarea datelor din rețea, citirea din baza de date sau procesarea array-urilor mari direct în onCreate blochează randarea primului cadru. Utilizatorul vede un ecran negru până când onCreate se finalizează, ceea ce degradează percepția vitezei aplicației. Soluție: utilizați lifecycleScope.launch pentru operații asincrone, afișați un schelet (placeholder UI) până la finalizarea încărcării.
Dacă la rotirea ecranului nu se restaurează starea din Bundle, utilizatorul pierde toată intrarea nesalvată: textul în câmpurile formularului, poziția de scroll, elementele selectate. Soluție: verificați întotdeauna savedInstanceState != null în onCreate pentru restaurarea datelor, chiar dacă pare că pierderea stării este puțin probabilă.
Clasele anonime și lambda-urile în onCreate pot reține implicit o referință la Activity după distrugerea sa. De exemplu, Handler-ul creat în onCreate continuă să execute sarcinile amânate chiar și după ce Activity a fost distrusă. Soluție: utilizați LifecycleObserver, ViewModel și lifecycleScope, care anulează automat sarcinile la distrugere.
Inițializarea View-ului în onCreate al Fragment — o eroare logică, deoarece View poate fi recreat fără apelarea onCreate. Dacă un ascultător este setat în onCreate, iar View este legat în onCreateView, la recreare ascultătorul rămâne pe View-ul vechi. Soluție: toată munca cu View se execută în onViewCreated, iar onCreate se lasă doar pentru inițializarea stratului de date.
Întrebări frecvente
Da, suprascrierea onCreate este obligatorie pentru orice Activity care afișează interfața utilizatorului. Fără aceasta, nu se poate apela setContentView și încărca aspectul XML. Dacă Activity nu are UI (de exemplu, o Activity-șablon transparentă), onCreate este totuși suprascris, dar fără apelarea setContentView.
Nu, onCreate nu poate fi apelat din nou pentru aceeași instanță de Activity. Dacă Activity este distrusă și recreată (rotirea ecranului, lipsă de memorie), aceasta este deja o instanță nouă cu un nou apel onCreate. Excepție — metoda recreate(), care forțează distrugerea și recrearea Activity, dar aceasta este tot o recreare a unei noi instanțe.
Dacă nu se apelează super.onCreate(savedInstanceState), Android Runtime va arunca excepția SuperNotCalledException și aplicația se va prăbuși. Sistemul cere strict ca fiecare metodă suprascrisă a ciclului de viață să-și apeleze versiunea super — aceasta garantează funcționarea corectă a mașinii de stări interne.
Diferența principală: onCreate din Activity încarcă UI prin setContentView, iar onCreate din Fragment doar inițializează datele. Fragment creează View-ul în metoda separată onCreateView, care poate fi apelată de mai multe ori (de exemplu, la comutarea filelor), în timp ce onCreate al Fragment este apelat o dată pe durata de viață a instanței Fragment.
Datele inițializate în onCreate se stochează în câmpurile clasei Activity sau Fragment. De exemplu, private lateinit var binding: ActivityMainBinding se declară la nivelul clasei, se inițializează în onCreate și este accesibilă în toate metodele ulterioare. Pentru datele care supraviețuiesc rotației ecranului, se utilizează ViewModel cu LiveData sau StateFlow.
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