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 КБ — перевищення ліміту викликає 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 мс, консоль позначає це як проблему продуктивності. Ми в 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
}
// Завантаження даних, якщо ViewModel щойно створено
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 для асинхронних операцій, відображайте скелетон (UI placeholder) до завершення завантаження.
Якщо при повороті екрану не відновлювати стан з Bundle, користувач втрачає весь незбережений ввід: текст у полях форми, позицію прокрутки, вибрані елементи. Рішення: завжди перевіряйте savedInstanceState != null в onCreate для відновлення даних, навіть якщо втрата стану здається майовірною.
Анонімні класи та лямбди в onCreate можуть неявно утримувати посилання на Activity після його знищення. Наприклад, Handler, створений в onCreate, продовжує виконувати відкладені завдання навіть після знищення Activity. Рішення: використовуйте LifecycleObserver, ViewModel та lifecycleScope, які автоматично скасовують завдання при знищенні.
Ініціалізація View в Fragment.onCreate — це логічна помилка, оскільки 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 року. Ми проконсультуємо вас і запропонуємо найкраще рішення.
Читайте також