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 г. Ще ви консултираме и ще предложим най-доброто решение.
Прочетете също