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 для асинхронных операций, отображать скелетон (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 оставлять только для инициализации data-слоя.
Часто задаваемые вопросы
Да, переопределение 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 года. Мы проконсультируем вас и предложим наилучшее решение.
Читайте также