onCreate — прва и једина обавезна метода животног циклуса Activity и Fragment у Android-у. Систем је позива једном приликом креирања компоненте, прослеђујући параметар Bundle са претходно сачуваним стањем. Унутар onCreate програмер иницијализује кориснички интерфејс, повезује View елементе, конфигурише руковаоце догађајима и враћа податке из savedInstanceState. Без исправне имплементације onCreate није могуће покренути ниједну Android апликацију — то је улазна тачка за сваки екран. Више о општем животном циклусу Activity прочитајте у чланку Activity Lifecycle.
Главне тачке
onCreate — метода повратног позива (callback) коју Android позива при креирању нове инстанце Activity или Fragment. Ово је прва улазна тачка у код корисничког екрана: пре позива onCreate ниједан кориснички код се не извршава. Систем прослеђује методи параметар Bundle, који или садржи претходно сачуване податке (при поновном креирању) или је једнак null (при првом покретању).
Метода onCreate је дефинисана у класи android.app.Activity и у класи androidx.fragment.app.Fragment. Обе варијанте обављају сличне задатке: иницијализација компоненте, подешавање UI и враћање стања. Међутим, конкретна имплементација се разликује — Activity користи setContentView за учитавање изгледа, а Fragment враћа View кроз onCreateView. Програмер је дужан да прегази барем onCreate у Activity — без тога Android не може да прикаже екран.
onCreate се позива строго једном током пуног животног циклуса инстанце Activity. Чак и при ротацији екрана, нова инстанца Activity добија нови позив onCreate са Bundle-ом од претходне инстанце. Ово својство чини onCreate идеалним местом за једнократну иницијализацију: учитавање података, креирање адаптера, подешавање DI компоненти кроз Dagger или Hilt.
У Activity метода onCreate обавља четири кључна задатка: учитавање layout изгледа, иницијализација View елемената, враћање стања из Bundle и подешавање примарних руковалаца догађајима. Обавезан минимални код у onCreate — позив super.onCreate(savedInstanceState) и setContentView(R.layout.activity_main).
class MainActivity : AppCompatActivity() {
private var binding: ActivityMainBinding? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// ViewBinding — модерна замена за findViewById
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding?.root)
// Иницијализација помоћу binding
binding?.apply {
welcomeText.text = getString(R.string.welcome)
startButton.setOnClickListener { startGame() }
}
// Враћање стања
if (savedInstanceState != null) {
score = savedInstanceState.getInt("score", 0)
binding?.scoreText?.text = score.toString()
}
}
}
Модерна пракса — коришћење ViewBinding уместо findViewById. ViewBinding генерише класу ActivityMainBinding у фази компилације, што елиминише грешке са нетачним ID-овима и смањује количину шаблонског кода. Google препоручује ViewBinding као стандардни начин приступа View-у у Activity и Fragment од Android Studio 3.6.
Редослед радњи у onCreate мора бити строг: прво super, затим setContentView, па све остало. Позив findViewById пре setContentView враћа null — изглед још није учитан, а View елементи не постоје у хијерархији. Ово је једна од најчешћих грешака почетника Android програмера.
onCreate у Fragment се разликује од Activity: овде се не позива setContentView, већ се извршава само иницијализација података који нису везани за UI. Fragment дели креирање компоненте и креирање View-а на два одвојена метода: onCreate (позива се једном) и onCreateView (позива се сваки пут при креирању или поновном креирању View-а).
class UserListFragment : Fragment() {
private lateinit var viewModel: UserViewModel
private var binding: FragmentUserListBinding? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// Иницијализација ViewModel — преживеће поновно креирање View
viewModel = ViewModelProvider(this)[UserViewModel::class.java]
// Аргументи из FragmentManager
arguments?.let {
viewModel.loadUser(it.getString("user_id") ?: "")
}
// Чување при ротацији
retainInstance = true
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
binding = FragmentUserListBinding.inflate(inflater, container, false)
return binding!!.root
}
}
Кључна разлика између onCreate Activity и Fragment: onCreate у Fragment не сме да садржи код везан за View, јер View може бити уништен и поново креиран (на пример, при пребацивању картица ViewPager-а), док се onCreate позива само једном. Учитавање података, подешавање ViewModel и иницијализација адаптера — задаци onCreate, а повезивање View-а — задатак onViewCreated.
Параметар savedInstanceState у onCreate — механизам за чување и враћање привременог стања Activity или Fragment. Када систем уништи Activity (ротација екрана, недостатак меморије), позива onSaveInstanceState(), у који програмер смешта пар кључ-вредност у Bundle. При креирању нове инстанце, овај Bundle се враћа у onCreate.
Bundle подржава следеће типове података: String, Integer, Boolean, Long, Float, Double, њихове низове, као и Parcelable и Serializable објекте. За сложене објекте користи се Parcelable — то је ефикаснији механизам серијализације, специфичан за Android. Величина Bundle је ограничена на приближно 500 KB — прекорачење границе изазива изузетак 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)
}
Важно је разумети: onSaveInstanceState се не позива када корисник експлицитно затвори Activity кроз finish() или притиском на дугме „Назад". Систем сматра да у овом случају корисник свесно завршава рад и чување стања није потребно. Због тога се не треба ослањати искључиво на savedInstanceState за дугорочно чување података — користите Room, DataStore или SharedPreferences.
onCreate се извршава у главној (UI) нити и систем чека његов завршетак пре него што прикаже Activity на екрану. Ако onCreate траје дуже од 5 секунди, систем приказује дијалог ANR (Application Not Responding) и предлаже кориснику затварање апликације. Дуготрајне операције, као што су учитавање података из мреже или читање из базе података, треба пребацити у позадинску нит.
Према препорукама Google Android Performance (2025), onCreate треба да се заврши за мање од 1 секунде на уређајима средњег сегмента. За то је потребно: користити лењу иницијализацију (lazy делегат у Kotlin-у), одложити учитавање тешких података у onResume или кроз корутине, применити ViewStub за ретко коришћене UI компоненте, профилисати време покретања кроз Android Vitals.
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// Лења иницијализација — објекат се креира само при првом обраћању
val heavyData by lazy {
HeavyDataLoader.load()
}
// Учитавање података у позадинској нити кроз lifecycleScope
lifecycleScope.launch(Dispatchers.IO) {
val users = userDao.getAllUsers()
withContext(Dispatchers.Main) {
adapter.submitList(users)
}
}
}
Алати за профилисање: Android Studio Profiler (картица CPU) показује тачно време извршавања сваке методе. У Android Vitals (конзола Google Play) можете пратити метрику „Време хладног покретања" — ако onCreate ваше Activity прелази 500 ms, конзола то означава као проблем перформанси. Ми у IT Sectr користимо Macrobenchmark тестове за аутоматску контролу времена покретања сваке Activity у CI цевоводу.
ViewModel — најбољи начин иницијализације података у onCreate који треба да преживе ротацију екрана. ViewModel се креира у onCreate кроз ViewModelProvider и аутоматски се чува при промени конфигурације. Када се Activity поново креира након ротације, ViewModel остаје у меморији и onCreate добија исти ViewModel без губитка података.
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_profile)
// ViewModel се креира једном и преживљава конфигурационе промене
val viewModel: ProfileViewModel =
ViewModelProvider(this)[ProfileViewModel::class.java]
// Посматрање LiveData — UI се аутоматски ажурира при промени података
viewModel.user.observe(this) { user ->
binding?.userName?.text = user.name
binding?.userEmail?.text = user.email
}
// Учитавање података ако је ViewManager тек креиран
if (savedInstanceState == null) {
viewModel.loadProfile(userId)
}
}
Комбинација ViewModel + LiveData/StateFlow решава проблем ротације екрана без ручног чувања у Bundle. ViewModel чува податке у меморији, LiveData аутоматски поново претплаћује Activity при поновном креирању, а StateFlow (из Kotlin Coroutines) додаје реактивност са подршком за корутине. Ово је стандардна архитектура коју Google препоручује у водичу Guide to App Architecture.
Чак и искусни програмери праве типичне грешке у onCreate. Размотримо пет најчешћих проблема и начине да их избегнемо.
Најчешћа грешка — покушај проналажења View кроз findViewById пре позива setContentView. Сви View елементи се креирају у тренутку инфлације изгледа, па свако обраћање findViewById-у пре setContentView враћа null и изазива NullPointerException при покушају коришћења View. Решење: строг редослед — прво super, затим setContentView, па findViewById или ViewBinding.
Учитавање података из мреже, читање из базе података или обрада великих низова директно у onCreate блокира приказивање првог кадра. Корисник види црни екран док се onCreate не заврши, што погоршава перцепцију брзине апликације. Решење: користити lifecycleScope.launch за асинхроне операције, приказати скелетон (placeholder UI) док се учитавање не заврши.
Ако се при ротацији екрана не враћа стање из Bundle-а, корисник губи сав несачуван унос: текст у пољима форме, позицију скрола, изабране елементе. Решење: увек проверавати savedInstanceState != null у onCreate за враћање података, чак и ако се чини да је губитак стања мало вероватан.
Анонимне класе и ламбде у onCreate могу имплицитно задржати референцу на Activity након његовог уништења. На пример, Handler креиран у onCreate наставља да извршава одложене задатке чак и након што је Activity уништена. Решење: користити LifecycleObserver, ViewModel и lifecycleScope, који аутоматски отказују задатке при уништењу.
Иницијализација View-а у onCreate Fragment — логичка грешка, јер View може бити поново креиран без позива onCreate. Ако се ослушкивач постави у onCreate, а View повеже у onCreateView, при поновном креирању ослушкивач остаје на старом View-у. Решење: сав рад са View-ом обављати у onViewCreated, а onCreate оставити само за иницијализацију слоја података.
Често постављана питања
Да, прегажење onCreate је обавезно за сваку Activity која приказује кориснички интерфејс. Без тога није могуће позвати setContentView и учитати XML изглед. Ако Activity нема UI (на пример, провидна Activity-заглушка), onCreate се ипак прегажава, али без позива setContentView.
Не, onCreate не може бити поново позван за исту инстанцу Activity. Ако је Activity уништена и поново креирана (ротација екрана, недостатак меморије), то је већ нова инстанца са новим позивом onCreate. Изузетак — метода recreate(), која принудно уништава и поново креира Activity, али то је поновно креирање нове инстанце.
Ако се не позове super.onCreate(savedInstanceState), Android Runtime ће бацити изузетак SuperNotCalledException и апликација ће се срушити. Систем строго захтева да свака прегажена метода животног циклуса позове своју super верзију — то гарантује исправан рад унутрашњег коначног аутомата стања.
Основна разлика: onCreate у Activity учитава UI кроз setContentView, а onCreate у Fragment само иницијализује податке. Fragment креира View у засебној методи onCreateView, која може бити позвана више пута (на пример, при пребацивању картица), док се onCreate Fragment позива једном током животног века инстанце Fragment.
Подаци иницијализовани у onCreate чувају се у пољима класе Activity или Fragment. На пример, private lateinit var binding: ActivityMainBinding се декларише на нивоу класе, иницијализује у onCreate и доступан је у свим наредним методама. За податке који преживљавају ротацију екрана користи се ViewModel са LiveData или StateFlow.
Резиме
Развићемо мобилну апликацију под кључ
IT Sectr креира iOS и Android апликације за стартапе и предузећа од 2017. године. Саветоваћемо вас и предложити најбоље решење.
Прочитајте такође