Жизненный цикл Android — SwiftBook
Понимание жизненного цикла Android и изменения его состояния имеет решающее значение для создания приложений с меньшим количеством ошибок, использующих меньше ресурсов и обеспечивающих хорошее взаимодействие с пользователем.
Когда дело доходит до создания приложения на Android, активити и фрагменты являются ключевыми компонентами для создания пользовательского интерфейса (UI). Когда пользователь перемещается по приложению, эти компоненты проходят через разные состояния жизненного цикла Android.
Понимание жизненного цикла и правильная реакция на изменения его состояния имеют решающее значение. Он позволяет создавать приложения с меньшим количеством ошибок, использовать меньше системных ресурсов Android и обеспечивать хорошее взаимодействие с пользователем.
В этом туториале вы познакомитесь с простым приложением PuppyCounter, которое можно использовать для подсчета собак во время прогулки по окрестностям.
- Роль жизненного цикла в Android приложениях.
- Основы жизненных циклов активити и фрагментов, а также колбэки (обратные вызовы), вызываемые, когда действие перемещается между состояниями жизненного цикла.
- Как сохранить и восстановить состояние экземпляра активити.
- Процесс передачи данных между активити и фрагментами.
- Как ViewModel может помочь вам хранить и управлять данными, связанными с пользовательским интерфейсом с учетом жизненного цикла.
Для этого урока вам понадобится Android Studio и Android-устройство или эмулятор.
Начнем
Для начала загрузите материалы. Откройте стартовый проект в Android Studio. Как только проект откроется, дайте ему запуститься и синхронизироваться, и вы будете готовы к работе!
Запустите приложение и проверьте его возможности:
В приложении два экрана:
- Главный экран: позволяет подсчитывать собак разных размеров.
Вы можете нажимать на карточки или на кнопки «плюс» и «минус», чтобы обновить счетчики. На верхней панели у вас есть две кнопки: первая сбрасывает значения, а вторая открывает экран «Share» (Поделиться). - Экран Share: показывает количество ваших собак. Нажмите на «Share», чтобы открыть диалоговое окно, в котором вас спросят, хотите ли вы поделиться своим счетом. В этом туториале вы не реализуете эту логику, но можете притвориться, что она существует. :]
Затем ознакомьтесь со структурой проекта:
Как видите, много, что для вас уже приготовлено. Самые важные пакеты — это активити и фрагменты. Вы будете перемещаться между ними, когда узнаете об активити и жизненном цикле фрагмента. Прямо сейчас не беспокойтесь о деталях. Вы познакомитесь с классами внутри по мере прохождения данного туториала. Помимо этих пакетов, обратите внимание на следующие три вещи:
- DogCount: класс модели для ваших данных.

- SplashActivity: активити, которая открывается при запуске приложения.
- PuppyCounterApplication: класс приложения.
Прежде чем вдаваться в подробности жизненного цикла активити, рассмотрим некоторую предысторию роли жизненного цикла в приложениях Android.
Понимание роли жизненного цикла приложений
Операционная система (ОС) Android — это многопользовательская система Linux. В большинстве случаев каждое приложение работает в собственном процессе Linux. ОС создает процесс, когда необходимо выполнить любой из компонентов приложения. Когда ни один компонент приложения не запущен, а ОС требуется освободить память для запуска других приложений, процесс прерывается.
ОС Android использует иерархию по важности, чтобы определить, какие процессы оставить в живых или уничтожить. В этой иерархии процессы делятся на разные типы. Этот тип зависит от запущенных в данный момент компонентов приложения и их текущего состояния.
Самый распространенный компонент приложения — Activity. Каждое приложение для Android имеет одно или несколько активити. Когда пользователь перемещается по приложению, действия проходят через разные состояния жизненного цикла.
Разработчики должны понимать, как различные компоненты влияют на время жизни процесса. Неправильное использование этих компонентов может привести к тому, что система остановит процесс, пока выполняет важную работу.
Изучение жизненного цикла активности
На рисунке выше показаны различные состояния, через которые происходит активность в течение своего жизненного цикла:
- Initialized: создается экземпляр активити и инициализируются его свойства.
- Created: активити теперь полностью инициализировано и готово к настройке своего пользовательского интерфейса.
- Started: активити видна пользователю.
- Resumed: активити видна пользователю и находится в фокусе.
В этом состоянии пользователь, скорее всего, взаимодействует с активити. - Destroyed: активити уничтожена, и ОС может освободить свою память.
Обратите внимание на разные колбэки (обратные вызовы) между состояниями. ОС вызывает эти колбэки, когда активити переходит из одного состояния в другое. Вы можете переопределить эти методы в своих активити, чтобы выполнять задачи в ответ на эти изменения состояния жизненного цикла.
Прежде чем объяснять каждый колбэк, проверьте их в действии. Откройте MainActivity.kt и добавьте логирование в onCreate() и onResume(). Также переопределите другие колбэки:
override fun onStart() {
Timber.i("PuppyCounter - MainActivity - onStart()")
super.onStart()
}
override fun onCreate(savedInstanceState: Bundle?) {
Timber.i("PuppyCounter - MainActivity - onCreate()")
super.onCreate(savedInstanceState)
setContentView(R.layout.layout_main)
findViews()
setupSmallDogViewsClickListeners()
setupMiddleDogViewsClickListeners()
setupBigDogViewsClickListeners()
}
override fun onResume() {
Timber.
i("PuppyCounter - MainActivity - onResume()")
super.onResume()
renderDogCount(dogCount)
}
override fun onPause() {
Timber.i("PuppyCounter - MainActivity - onPause()")
super.onPause()
}
override fun onStop() {
Timber.i("PuppyCounter - MainActivity - onStop()")
super.onStop()
}
override fun onDestroy() {
Timber.i("PuppyCounter - MainActivity - onDestroy()")
super.onDestroy()
} Всякий раз, когда вы переопределяете такой колбэк, убедитесь, что вы также вызываете метод суперкласса. Если вы этого не сделаете, ваше приложение не выполнит какую-то важную работу и может вылететь или зависнуть.
Скомпилируйте и запустите приложение. Затем проверьте логи. Чтобы просмотреть логи в Android Studio, откройте инструмент Logcat, щелкнув Logcat внизу на странице. Введите PuppyCounter в историю поиска, чтобы показать результаты:
Затем закройте приложение, нажав назад, или проведите пальцем в обратном направлении, если у вас включена навигация с помощью жестов.
Еще раз проверьте логи. Вы должны увидеть что-то вроде этого:
Заметка
В логах вы не увидите сообщение «Back button clicked» (Нажата кнопка назад). Мы добавили это в изображение, чтобы вам было легче заметить нажатия кнопок.
Понимание колбэков жизненного цикла активити
Вы только что прошли один полный жизненный цикл активити: активити была создана, возобновлена и окончательно уничтожена, когда вы вышли из приложения.
На приведенной выше диаграмме представлен жизненный цикл активити:
- onCreate(): активити переходит в состояние Создано. Здесь вы выполняете логику, которая должна выполняться только один раз за все время активити. Сюда можно включить настройку контент вью, связывание активити с ViewModel, создание экземпляров некоторых переменных области класса и т.д.
- onStart(): активити переходит в состояние Начато. Этот вызов делает активити видимой для пользователя, поскольку приложение готовится к тому, чтобы активити перешла на передний план и стала интерактивной.

- onResume(): активити переходит в состояние Возобновлено. Теперь пользователь может взаимодействовать с активити. Здесь вы можете включить любую функциональность, которая должна работать, пока компонент виден и находится на переднем плане.
- onPause(): активити переходит в состояние Приостановлено. Этот вызов указывает на то, что активити больше не находится на переднем плане, хотя она может быть видна, например, если пользователь находится в многооконном режиме. В это время вам следует приостановить или настроить операции, которые не должны продолжаться или должны продолжаться в модерации. Действие остается в этом состоянии до возобновления активити, например, открытия или закрытия нижнего листа в действии, или до тех пор, пока оно не станет полностью невидимым для пользователя, например, при открытии другого действия.
- onStop(): активити переходит в состояние Остановлено.

Активити больше не видна пользователю. Здесь вы должны освободить или настроить ресурсы, которые не нужны, пока активити не видна пользователю. Вы также должны использовать эту возможность для выполнения операций выключения для задач, которые относительно интенсивно загружают процессор, например, для операций с базой данных. - onDestroy(): активити переходит в состояние Уничтожено. На этом работа заканчивается. Это может быть потому, что:
- Пользователь полностью закрывает активити.
- finish() вызывается для активити.
- Система временно прерывает активити из-за изменения конфигурации, например поворота устройства или многооконного режима.
Бывают ситуации, когда система убивает процесс, следовательно, не вызывает onDestroy() или любые другие методы жизненного цикла активити. Таким образом, его не следует использовать для того, чтобы делать те вещи, которые должны остаться после завершения процесса.
Заметка
Дополнительные сведения о жизненном цикле Activity смотрите в Android Developer documentation.
Сохранение и восстановление состояния экземпляра активити
Если вы немного поиграли с приложением, то возможно, заметили пару ошибок. Счетчик увеличивается при нажатии карточек на главном экране.
Теперь поверните устройство, чтобы изменить ориентацию экрана. Если на дисплее вашего устройства включен автоповорот, вы увидите что-то вроде этого:
Состояние счетчика обнулилось при смене ориентации экрана. Посмотрим логи:
Вы можете видеть, что когда поменялась ориентация экрана, приложение уничтожило активити в портретной ориентации, а затем создало и возобновило новую активити в горизонтальной ориентации. Поскольку в MainActivity.kt у вас нет никакой логики для сохранения и восстановления состояния счетчика, действие было потеряно во время этого процесса.
Скоро мы это исправим!
Сохранение состояния экземпляра
Откройте MainActivity.kt и добавьте следующий код:
override fun onSaveInstanceState(outState: Bundle) {
Timber.
i("PuppyCounter - MainActivity - onSaveInstanceState()")
// Save the dog count state
outState.putParcelable(STATE_DOG_COUNT, dogCount)
// Always call the superclass so it can save the view hierarchy state
super.onSaveInstanceState(outState)
}Когда активити начинает останавливаться, ОС вызывает onSaveInstanceState(), чтобы действие сохранило любую информацию о состоянии в бандле сохранения состояния. Некоторые вью Android обрабатывают по умолчанию — EditText для текста и ListView для позиции прокрутки.
Заметка
OnSaveInstanceState() не вызывается, когда пользователь явно закрывает активити или когда вызывается finish().
Чтобы сохранить состояние dogCount, вы переопределили onSaveInstanceState() и сохранили состояние в Bundle как пару ключ-значение с помощью outState.putParcelable(). В качестве ключа вы использовали STATE_DOG_COUNT, который уже был определен в классе.
Проверьте класс DogCount. Вы заметите, что он реализует Parcelable.
Если вы не знакомы с Parcelable — это интерфейс, концептуально похожий Serializable в Java. Классы, реализующие Parcelable, могут быть записаны и восстановлены из Parcel, который разработан для высокопроизводительного транспорта IPC (IPC transport). Проще говоря, он позволяет хранить простые структуры данных в Bundle.
Восстановление состояния
Прекрасно! Теперь у вас есть логика для сохранения состояния, но в ней нет пользы, пока у вас нет логики для ее получения. В
override fun onRestoreInstanceState(savedInstanceState: Bundle) {
Timber.i("PuppyCounter - MainActivity - onRestoreInstanceState()")
// Always call the superclass so it can restore the view hierarchy
super.onRestoreInstanceState(savedInstanceState)
dogCount = savedInstanceState.getParcelable(STATE_DOG_COUNT) ?: DogCount()
}Любое состояние, которое вы сохраняете в onSaveInstanceState(), вы можете восстановить в onRestoreInstanceState().
onRestoreInstanceState() получает Bundle, который содержит пары ключ-значение, которые вы можете прочитать. Здесь вы использовали saveInstanceState.getParcelable() для получения состояния DogCount. Обратите внимание, что вы использовали тот же ключ, что и для сохранения состояния: STATE_DOG_COUNT.
Заметка
ОС вызывает onRestoreInstanceState() после обратного вызова onStart(), только если у нее есть сохраненное состояние для восстановления. Вы также можете восстановить состояние в onCreate(), потому что этот колбэк получает тот же Bundle.
Запустите приложение. Увеличьте значения счетчиков и поменяйте ориентацию экрана:
Также проверьте логи, когда все колбеки будут вызваны, вы увидите следующую картину:
Заметка
Не путайте onSaveInstanceState() и onRestoreInstanceState() с колбеками жизненного цикла активности. ОС вызывает эти методы только в тот момент, когда это нужно.
Отлично! Теперь, когда вы исправили ошибку в приложении, пора перейти к следующей.
🙂
Передача данных между экранами
Увеличьте значения счетчиков на главном экране, а затем откройте экран «Share». Вы заметите, что значения экрана «Share» не совпадают со значениями на главном экране.
В MainActivity.kt измените showShareScreen() следующим образом:
private fun showShareScreen() {
Timber.i("PuppyCounter - MainActivity - start ShareActivity Intent")
val intent = ShareActivity.createIntent(this)
// Store DogCount state to the intent
intent.putExtra(ShareActivity.EXTRA_DOG_COUNT, dogCount)
startActivity(intent)
}С помощью этого кода вы сохраняете состояние DogCount в Intent. Здесь вы используете подход, аналогичный тому, что вы видели в предыдущем разделе. Да, этим вы передадите данные в ShareActivity, но вам все равно нужно добавить логику для их получения.
В ShareActivity.kt добавьте следующий метод:
private fun readExtras() = intent.extras?.run { Timber.i("PuppyCounter - ShareActivity - readExtras()") dogCount = getParcelable(EXTRA_DOG_COUNT) ?: DogCount() }
Этот метод извлекает объект Intent, который запустил это действие, и пытается получить дополнительные данные, которые были переданы с ним. В этом конкретном случае он попытается получить состояние DogCount.
Чтобы завершить логику получения, вызовите этот метод в onCreate() в ShareActivity.kt:
override fun onCreate(savedInstanceState: Bundle?) {
Timber.i("PuppyCounter - ShareActivity - onCreate()")
super.onCreate(savedInstanceState)
setContentView(R.layout.layout_share)
findViews()
// Read extra data from the Intent
readExtras()
setOnShareBtnClickListener()
}При получении данных из Intent лучше всего это сделать в onCreate(). Таким образом, у вас будет время настроить состояние до того, как действие возобновится и пользователь начнет с ним взаимодействовать.
Супер! Запустите приложение. Увеличьте значения счетчиков и откройте экран «Share». Вы увидите что-то вроде этого:
Проверьте логи, чтобы увидеть жизненные циклы активити при переходе от одного экрана к другому.
Обратите внимание, как ОС создает ShareActivity сразу после вызова onPause() MainActivity. Как упоминалось ранее, приложение вызывает onStop(), когда активити больше не видна пользователю. После вызова onPause() MainActivity вы можете увидеть серию колбэков жизненного цикла ShareActivity, которые включают чтение intent данных. После возобновления ShareActivity полностью виден пользователю, и может быть вызвана функция MainActivity onStop(), за которой следует onSaveInstanceState().
Разбираем данные объекта Intent
Измените ориентацию экрана на экране Share и обратите внимание на то, что происходит. Вы увидите, что приложение сохранило состояние dogCount.
Как это возможно, если вы не реализовали логику для сохранения и получения состояния экземпляра?
Проверяйте логи! 🙂
Вы уже знакомы с тем, как состояние может быть потеряно во время изменения конфигурации. В этом случае обратите внимание на то, что лог readExtras() снова присутствует, когда приложение создает новый ShareActivity. Но если вы проверите код, вы увидите, что вы распечатываете этот лог, только если intent.extras отличается от null — или, другими словами, Intent содержит некоторые данные.
Данные, которые вы передаете с помощью Intent при запуске новой активити, сохраняются при воссоздании активити.
Чтобы завершить этот раздел, нажмите назад, когда экран находится в горизонтальной ориентации, и еще раз просмотрите логи.
ShareActivity приостановлен, а старая портретная активность MainActivity уничтожена. Затем создается и возобновляется новая горизонтальная MainActivity.
Наконец, приложение вызывает onStop() и onDestroy() ShareActivity.
Отлично! Теперь, когда вы понимаете жизненный цикл активности и то, как правильно управлять состоянием активити, пора переходить к фрагментам. 🙂
Изучение жизненного цикла фрагмента
Как и у активити, у фрагментов есть свой жизненный цикл. Когда пользователь перемещается по вашему приложению и взаимодействует с ним, ваши фрагменты переходят из одного состояния в другое в своем жизненном цикле, когда они добавляются, удаляются, а также выходят на экран или выходят из него.
На рисунке выше вы можете видеть, что жизненный цикл фрагмента аналогичен жизненному циклу активити, но содержит некоторые дополнительные методы, специфичные для фрагмента. Прежде чем объяснять каждый колбэк, проверьте их в приложении.
В предыдущем разделе вы поиграли с двумя активити и увидели, как меняется их жизненный цикл при перемещении между экранами. В этом примере вы реализуете те же экраны с фрагментами.
Вы можете найти два фрагмента, которые представляют каждый экран в пакете фрагментов: MainFragment.kt и ShareFragment.kt. Также есть одна активити контейнера и пакет viewmodels. Пока не обращайте внимания на пакет viewmodels. Он понадобится вам в следующем разделе.
Если вы проверите MainFragment.kt, вы заметите много общего с MainActivity.kt. У них одинаковая логика управления состояниями, но MainFragment.kt содержит еще несколько колбэков жизненного цикла.
Перед запуском приложения откройте SplashActivity.kt и обновите startFirstActivity(), чтобы он запускал ActivityWithFragments вместо MainActivity:
private fun startFirstActivity() {
startActivity(Intent(this, ActivityWithFragments::class.java))
}Отлично! Теперь соберите и запустите приложение. Затем осмотрите логи.
Обратите внимание, как жизненный цикл фрагмента синхронизируется с жизненным циклом активности.
Сначала приложение создает и запускает ActivityWithFragments. После этого он создает и запускает фрагмент и его просмотр. Наконец, он возобновляет как активити, так и фрагмент.
Далее нажмите назад и снова наблюдайте за логами.
Закрыв приложение, вы запустили процесс уничтожения активити. Как и раньше, события жизненного цикла фрагмента следуют за событиями жизненного цикла активити. И активити, и фрагмент сначала приостанавливаются, затем останавливаются и, наконец, уничтожаются.
Состояние жизненного цикла фрагмента никогда не может быть выше, чем у его родительского. Например, родительский фрагмент или активити должны начинаться до его дочерних фрагментов. Точно так же дочерние фрагменты должны останавливаться до их родительского фрагмента или активности. Из приведенных выше логов можно подумать наоборот — что сначала останавливается действие, но это только потому, что вы распечатываете логи как первый вызов в колбэках жизненного цикла.
Внутренне ОС обеспечивает остановку всех дочерних фрагментов перед остановкой активити.
Понимание обратных вызовов жизненного цикла фрагмента
Теперь вы можете немного глубже погрузиться в каждое событие жизненного цикла, чтобы лучше понять жизненный цикл фрагмента:
- onCreate(): фрагмент достигает состояния Created. Подобно onCreate() активити, этот колбэк получает Bundle, содержащий любое состояние, ранее сохраненное onSaveInstanceState().
- onCreateView(): вызывается для расширения или создания вью фрагмента.
- onViewCreated(): вью фрагмента создается с ненулевым объектом View. Это представление устанавливается для фрагмента и может быть получено с помощью getView().
- onStart(): фрагмент переходит в состояние Started. В этом состоянии гарантируется, что вью фрагмента доступно и безопасно выполнить FragmentTransaction для дочернего FragmentManager фрагмента.

- onResumed(): фрагмент переходит в состояние Resumed. Он становится видимым после завершения всех эффектов Animator и Transition. Теперь пользователь может взаимодействовать с фрагментом.
- onPause(): фрагмент возвращается в состояние Started. ОС вызывает этот колбэк, когда пользователь начинает покидать фрагмент, пока фрагмент все еще виден.
- onStop(): фрагмент возвращается в состояние Created и больше не отображается.
- onDestroyView(): запускается после завершения всех анимаций выхода и переходов, когда представление фрагмента было отделено от окна. На этом этапе все ссылки на представление фрагмента должны быть удалены, что позволит очистить представление фрагмента от мусора.
- onDestroy(): фрагмент переходит в состояние Destroyed. Это происходит при удалении фрагмента или при уничтожении FragmentManager.
На этом этапе жизненный цикл фрагмента подошел к концу.
Теперь, когда вы лучше понимаете, что скрывается под капотом, переходите между основным экраном и экраном Share, чтобы увидеть танец жизненного цикла фрагмента. 🙂
Как вы видели в этом и предыдущем разделе, жизненный цикл Android довольно сложен. Управлять состояниями и взаимодействовать с пользовательским интерфейсом в нужное время может быть непросто для неопытных разработчиков. Это привело к появлению некоторых новых API и компонентов Android, которые должны облегчить жизнь всем разработчикам Android. Одним из таких компонентов является ViewModel.
Использование ViewModel для хранения данных пользовательского интерфейса
ViewModel предназначен для хранения данных, связанных с пользовательским интерфейсом, и управления ими с учетом жизненного цикла.
Во-первых, замените логику сохранения и восстановления состояния в MainFragment.kt подходом, использующим ViewModel.
В пакете viewmodels создайте новый класс с именем MainViewModel.kt.
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import com.raywenderlich.android.puppycounter.model.DogCount
class MainViewModel : ViewModel() {
private val _dogCount: MutableLiveData by lazy {
MutableLiveData(DogCount())
}
val dogCount: LiveData = _dogCount
fun setDogCount(dogCount: DogCount) {
_dogCount.value = dogCount
}
}Это будет ViewModel для вашего главного экрана. Вы будете использовать его для сохранения состояния DogCount. Используйте _dogCount для отслеживания состояния и dogCount для отображения его наблюдателям. Для обновления состояния используйте setDogCount().
Если вы хотите узнать больше о LiveData, обратитесь к Android Developer documentation.
В MainFragment.
kt добавьте следующее:
import androidx.fragment.app.viewModels import com.raywenderlich.android.puppycounter.fragments.viewmodels.MainViewModel
Добавьте следующую строку выше onCreate():
private val viewModel: MainViewModel by viewModels()
Таким образом, вы добавили код для создания MainViewModel для MainFragment.
Затем добавьте в MainFragment.kt следующий метод:
private fun subscribeToViewModel() {
viewModel.dogCount.observe(viewLifecycleOwner, { value ->
dogCount = value
renderDogCount(dogCount)
})
}Этот метод позволяет вам подписаться на наблюдаемое состояние в MainViewModel. Каждый раз, когда состояние dogCount изменяется, приложение передает новое состояние во вью, и с новым состоянием вызывается renderDogCount(), в результате чего пользовательский интерфейс обновляется.
Затем измените onViewCreated(), чтобы подписаться на MainViewModel после вызова суперкласса:
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
Timber.
i("PuppyCounter - MainFragment - onViewCreated()")
super.onViewCreated(view, savedInstanceState)
subscribeToViewModel()
findViews(view)
setupSmallDogViewsClickListeners(view)
setupMiddleDogViewsClickListeners(view)
setupBigDogViewsClickListeners(view)
}Вам также понадобится логика, которая обновит состояние в MainViewModel. Измените updateDogCount() следующим образом:
private fun updateDogCount(newDogCount: DogCount) {
viewModel.setDogCount(newDogCount)
}Этот метод вызывается всякий раз, когда пользователь обновляет счетчики. Он обновит MainViewModel с новым состоянием. MainViewModel протолкнет это состояние через dogCount, и MainFragment получит уведомление, поскольку он подписан на MainViewModel.
Наконец, в MainFragment удалите onSaveInstanceState(), вызов renderDogCount (dogCount) из onResume() и код saveInstanceState? .Run {…} в onCreate(). Вам это больше не нужно. 🙂
Скомпилируйте и запустите приложение.
Коснитесь счетчиков пару раз и поверните экран. Вы должны увидеть что-то вроде этого:
На приведенном ниже рисунке можно увидеть время жизни ViewModel рядом с соответствующим жизненным циклом действия.
Объекты ViewModel привязаны к Lifecycle, передаваемому ViewModelProvider при получении ViewModel. Он остается в памяти до тех пор, пока Lifecycle, на который он рассчитан, не исчезнет навсегда. В случае активити это происходит, когда она завершена. Для фрагмента это происходит, когда он отсоединяется.
Оригинал статьи
Жизненный цикл приложения
Read this manual in English
Жизненный цикл приложения или игры, созданных в Defold, в целом прост. Движок проходит три стадии выполнения: инициализация, цикл обновления (в котором приложения и игры проводят большую часть времени) и финальная стадия.
В большинстве случаев необходимо лишь элементарное понимание внутренних рабочих процессов Defold. Однако возможны случаи, когда точный порядок исполнения задач становится критически важным.
В этом документе описывается, как движок запускает приложение от начала и до конца.
Загрузка приложения начинается с инициализации всех составляющих, необходимых для запуска движка. Происходит загрузка главной коллекции и вызов init() во всех загруженных компонентах, имеющих Lua-функцию init() (компоненты Script и GUI с GUI-скриптами). Это дает возможность выполнять пользовательскую инициализацию.
Затем приложение входит в цикл обновления, в котором оно будет находиться большую часть времени своего жизненного цикла. В каждом кадре обновляются игровые объекты и содержащиеся в них компоненты. Вызываются любые функции update() в скриптах и GUI-скриптах. В ходе цикла обновления адресатам отправляются сообщения, воспроизводятся звуки и отрисовывается вся графическая составляющая.
В какой-то момент жизненный цикл приложения завершается. Перед завершением приложения движок выходит из цикла обновления и вступает в стадию завершения. Он подготавливает все загруженные игровые объекты к удалению.
Вызываются функции final() всех компонентов объекта, что позволяет произвести пользовательскую очистку. Затем объекты удаляются, а основная коллекция выгружается.
Инициализация
Эта диаграмма подробно иллюстрирует шаги инициализации. Этапы, связанные с передачей “посланных сообщений” (непосредственно перед “порождением динамических объектов”), для наглядности были вынесены в отдельный блок справа.
На самом деле движок выполняет гораздо больше шагов во время инициализации перед загрузкой основной коллекции. Происходит настройка профилировщика памяти, сокетов, графики, HID (устройств ввода), звука, физики и т.д. Кроме того, загружается и настраивается конфигурация приложения (“game.project”).
Первой подконтрольной пользователю точкой входа в конце инициализации движка является вызов функции init() актуального рендер-скрипта.
Затем загружается и инициализируется основная коллекция.
Все игровые объекты в коллекции применяют свои трансформации (перемещение (изменение положения), вращение и масштабирование) к своим дочерним объектам. После этого вызываются все существующие функции init() компонентов.
Порядок, в котором вызываются функции init() компонентов игровых объектов, не определен. Не следует считать, что движок инициализирует объекты, принадлежащие одной коллекции, в определенном порядке.
Поскольку код функции init() может посылать новые сообщения, приказывать фабрикам порождать новые объекты, отмечать объекты для удаления и совершать другие действия, движок осуществляет очередной полный проход “постобновления”. Этот проход выполняет доставку сообщений, фактическое порождение игровых объектов фабриками и удаление объектов. Следует иметь в виду, что проход постобновления включает последовательность “диспетчеризации сообщений”, которая не только отправляет все поставленные в очередь сообщения, но и обрабатывает сообщения, отправленные прокси коллекциям.
Любые последующие обновления прокси (включение и отключение, загрузка и пометка для выгрузки) выполняются во время этих шагов.
Изучение приведенной выше диаграммы показывает, что вполне возможно загрузить прокси-коллекцию во время init(), обеспечить инициализацию всех содержащихся в ней объектов, а затем выгрузить коллекцию через прокси — и все это до вызова update() первого компонента, то есть до того, как движок выйдет из стадии инициализации и войдет в цикл обновления:
function init(self)
print("init()")
msg.post("#collectionproxy", "load")
end
function update(self, dt)
-- Прокси-коллекция выгружается до того, как этот код будет достигнут.
print("update()")
end
function on_message(self, message_id, message, sender)
if message_id == hash("proxy_loaded") then
print("proxy_loaded. Init, enable and then unload.")
msg.post("#collectionproxy", "init")
msg.post("#collectionproxy", "enable")
msg.post("#collectionproxy", "unload")
-- Функции init() и final() объектов прокси-коллекции
-- вызываются до того, как будет достигнута функция update() этого объекта
end
end
Цикл обновления
Цикл обновления проходит через длинную последовательность один раз в каждом кадре.
Последовательность обновления на диаграмме ниже разделена логически на блоки последовательности для наглядности. “Диспетчеризация сообщений” также разбита отдельно по той же причине:
Ввод
Ввод считывается с доступных устройств, сопоставляется с привязкой ввода и затем диспетчеризируется. Любой игровой объект, получивший фокус ввода, получает ввод, отправляемый всем функциям on_input() его компонентов. Игровой объект со скриптом и компонент GUI с GUI-скриптом будут получать ввод в функции on_input() своих компонентов, с учетом того, что они определены и что они получили фокус ввода.
Любой игровой объект, получивший фокус ввода и содержащий прокси-коллекции, направляет ввод компонентам внутри этой прокси-коллекции. Этот процесс продолжается рекурсивно вниз по включенным прокси-коллекциям внутри включенных прокси-коллекций.
Обновление
Каждый компонент игрового объекта в основной коллекции будет обследован.
Если у какого-либо из этих компонентов имеется функция update(), то вызывается именно она. Если компонент является прокси-коллекцией, то каждый компонент в прокси-коллекции рекурсивно обновляется с выполнением всех шагов в последовательности “обновления”, представленной на диаграмме выше.
Порядок вызова функций update() компонентов игровых объектов не определен. Не следует полагать, что движок обновляет объекты, принадлежащие одной коллекции, в определенном порядке.
На следующем этапе все отправленные сообщения диспетчеризируются. Поскольку код on_message() любого компонента-приемника может отправлять дополнительные сообщения, диспетчер сообщений будет продолжать диспетчеризацию отправленных сообщений до тех пор, пока очередь сообщений не опустеет. Однако существует ограничение на количество проходов по очереди сообщений, выполняемых диспетчером сообщений. За подробностями обращайтесь к руководству по передачи сообщений и к разделу “Дополнительные темы”.
Для объектов столкновения, сообщения физики (столкновения, триггеры, ответы ray_cast и т.д.) рассылаются по всему объемлющему игровому объекту всем компонентам, которые содержат скрипт с функцией on_message().
Затем осуществляются трансформации, применяя любое перемещение, вращение и масштабирование игрового объекта к каждому его компоненту и всем компонентам дочерних игровых объектов.
Рендер обновление
Рендер обновление блокирует диспетчеризацию сообщений в сокет @render (сообщение камеры set_view_projection, сообщение set_clear_color и др.). Также вызывается update() в рендер-скрипте.
Постобновление
После обновлений выполняется последовательность постобновления. Она выгружает из памяти прокси-коллекции, которые помечены для выгрузки (это происходит во время последовательности “диспетчеризации сообщений”).
Любой игровой объект, помеченный для удаления, вызывает функции final() всех своих компонентов, если таковые имеются. Код в функциях final() часто посылает новые сообщения в очередь, поэтому после этого выполняется проход “диспетчеризации сообщений”.
Далее любой компонент Factory, которому было указано породить игровой объект, выполнит это. Наконец, игровые объекты, помеченные для удаления, действительно удаляются.
Последний шаг в цикле обновления включает отправку @system-сообщений (сообщения exit, reboot, переключение профайлера, запуск и остановка захвата видео и т.д.). Затем происходит рендеринг графики. Во время рендеринга графики производится захват видео, а также визуальный профайлер (см. документацию по отладке.)
Частота кадров и временной шаг коллекции
Количество кадров, обновляемых в секунду (что равно количеству циклов обновления в секунду), можно установить в настройках проекта или программно, отправив сообщение set_update_frequency в сокет @system.
Кроме того, можно установить шаг времени для прокси-коллекции индивидуально, отправив в прокси сообщение set_time_step. Изменение временного шага коллекции не влияет на частоту кадров. Оно влияет на шаг времени обновления физики, а также на переменную dt, передаваемую в update(). Кроме того, следует отметить, что изменение шага времени не изменяет количество вызовов update() в каждом кадре — оно всегда ровно 1.
(За подробностями обращайтесь к документации по прокси-коллекциям и set_time_step)
Финальная стадия
При выходе из приложения сначала завершается последняя последовательность цикла обновления, которая выгружает все прокси-коллекции: завершает и удаляет все игровые объекты в каждой прокси-коллекции.
После этого движок переходит к завершающей последовательности, которая обрабатывает основную коллекцию и ее объекты:
Сначала вызываются компонентные функции final().
Затем следует очередная диспетчеризация сообщений. Наконец, все игровые объекты удаляются, а основная коллекция выгружается.
После этого движок выполняет закулисное отключение подсистем: конфигурация проекта удаляется, профилировщик памяти отключается и т.д.
Теперь приложение считается полностью закрытым.
Что такое управление жизненным циклом приложений (ALM)?
перейти к содержаниюВведите ключевые слова
Поддержка Приставка Начать пробную версию Контакт
Выберите язык 简体中文EnglishFrançaisDeutschItaliano日本語한국어PortuguêsEspañol
Связаться с намиВыберите язык.0011 한국어
Добро пожаловать,
Войдите в свою учетную запись Red Hat
Войдите в систему
Ваша учетная запись Red Hat дает вам доступ к вашему профилю участника и предпочтениям, а также к следующим услугам в зависимости от вашего статуса клиента:
Зарегистрируйтесь сейчас
Еще не зарегистрированы? Вот несколько причин, по которым вы должны это сделать:
- Просматривайте статьи базы знаний, управляйте обращениями в службу поддержки и подписками, загружайте обновления и многое другое из одного места.

- Просмотрите пользователей в вашей организации и измените информацию об их учетных записях, предпочтениях и разрешениях.
- Управляйте своими сертификатами Red Hat, просматривайте историю экзаменов и загружайте логотипы и документы, связанные с сертификацией.
Изменить свой профиль и настройки
Ваша учетная запись Red Hat дает вам доступ к вашему профилю участника, настройкам и другим услугам в зависимости от вашего статуса клиента.
В целях безопасности, если вы находитесь на общедоступном компьютере и завершили использование служб Red Hat, обязательно выйдите из системы.
Выход из системы
Логин аккаунтаВыберите язык
- 简体 中文
- Английский
- Français
- Deutsch
- ИТАЛАНАО
- 日本語
- 한국어
- PortuguêS
- ESPAYOL
- PortuguS
Управление жизненным циклом приложений (ALM) — это люди, инструменты и процессы, которые управляют жизненным циклом приложения от концепции до конца жизни.

ALM состоит из нескольких дисциплин, которые часто были разделены в рамках устаревших процессов разработки, таких как метод водопадной разработки, включая управление проектами, управление требованиями, разработку программного обеспечения, тестирование и обеспечение качества, развертывание и обслуживание.
Управление жизненным циклом приложений поддерживает подходы Agile и DevOps к разработке, объединяя эти дисциплины вместе и позволяя командам более эффективно сотрудничать в вашей организации.
Внедрение ALM также приводит к непрерывной доставке программного обеспечения и обновлений с частыми выпусками, иногда по нескольку раз в день, в отличие от новых выпусков, выходящих только раз в несколько месяцев или раз в год.
Управление жизненным циклом приложений обеспечивает основу для разработки программного обеспечения, а также помогает вам управлять своим программным обеспечением с течением времени. В соответствии с практиками ALM используется облегченный, заранее установленный план и требования для превращения идеи в приложение.

Приступая к разработке программного обеспечения с помощью ALM, необходимо учитывать весь срок службы приложения. Необходимо учитывать техническое обслуживание и будущие обновления, в том числе когда приложение должно быть удалено и заменено.
Объединяя эти элементы, ALM обеспечивает более быстрое развертывание, улучшенную видимость вашего рабочего процесса, продукты более высокого качества и повышение удовлетворенности разработчиков.
ALM помогает обеспечить наглядность процесса разработки. Поскольку процесс интегрирован, вы можете видеть, какой прогресс был достигнут, какие шаги еще нужно выполнить, сколько времени это занимает, какие тесты были завершены и многое другое.
Управление приложением
Управление описывает решения, принятые в отношении приложения. Когда вы начнете процесс создания нового приложения, вы начнете с первоначальной идеи для приложения, а также должны рассмотреть, как оно соотносится с потребностями и целями вашего бизнеса.

Это дополняет требования к новому приложению, которые необходимо определить и согласовать на этапе управления.
Управление ресурсами, данными и безопасностью, а также доступом пользователей являются дополнительными компонентами управления приложениями.
Стандартизация этих процессов позволяет автоматизировать управление. Автоматизация этих процессов управления ускорит доставку приложений.
Разработка приложения
После определения и согласования требований к приложению или обновлению можно приступать к разработке. Команды, которые следуют гибкой методологии разработки, могут заниматься разработкой и развертыванием один или даже несколько раз в день.
Проектирование, создание, тестирование и развертывание приложения можно считать частью этапа разработки.
Тестирование программного обеспечения
После того, как новое приложение будет разработано, его необходимо протестировать и устранить ошибки, прежде чем переходить к производству.

Для agile-команд и DevOps-команд тестирование должно происходить одновременно с разработкой. Обратная связь должна постоянно передаваться команде разработчиков.
Непрерывная интеграция должна быть частью процесса разработки, чтобы эти частые обновления не конфликтовали друг с другом.
Цель этапа тестирования — убедиться, что требования, изложенные руководством, выполнены и что приложение работает должным образом, прежде чем оно будет выпущено для пользователей.
Эксплуатация и обслуживание
После завершения тестирования и исправления необходимых ошибок приложение можно развернуть для пользователей.
Этап эксплуатации и обслуживания — это то, что фокусирует ALM на всем жизненном цикле приложения. Эксплуатация не заканчивается после развертывания приложения. Необходимо учитывать регулярное техническое обслуживание и обновления.
Прекращение использования приложения или службы также следует рассматривать как часть технического обслуживания.
Команды должны определить, в какой момент приложение больше не будет поддерживаться или станет доступна более новая версия.ALM в сравнении с SDLC
ALM иногда путают с жизненным циклом разработки программного обеспечения (SDLC), поскольку оба они связаны с процессом разработки программного обеспечения. Основное отличие заключается в том, что SDLC в первую очередь ориентирован на этап разработки, тогда как ALM занимается всем жизненным циклом приложения, от концепции до обслуживания и, в конечном итоге, вывода из эксплуатации, и продолжается после разработки приложения.
SDLC можно рассматривать как часть управления жизненным циклом приложения, прежде всего на этапах разработки, тестирования и развертывания. ALM может включать несколько жизненных циклов разработки для данного приложения.
Инструменты ALM в основном функционируют как инструменты управления проектами, которые помогают вам объединять людей и процессы. Ищите инструмент, который включает в себя контроль версий, возможность для команд общаться в режиме реального времени, функции управления требованиями, оценку и планирование проектов, управление исходным кодом и управление тестированием.

Вы можете найти все необходимые функции в одном инструменте или вам может потребоваться интеграция с дополнительными инструментами — например, инструментами для разработчиков. Выбранный вами инструмент ALM также должен поддерживать ваш процесс разработки, будь то Agile, водопад, DevOps или что-то еще.
Примеры инструментов ALM:
- Atlassian Jira
- Решения IBM ALM
- CA Agile Central
- Microsoft Azure DevOps Server
- Basec
- 2 Tuleap
- 20012
ALM поддерживает подход DevOps, который тесно связан с контейнерами Linux®. Контейнеры предоставляют вашей команде базовые технологии, необходимые для облачного стиля разработки, и поддерживают единую среду для разработки, доставки, интеграции и автоматизации.
А Kubernetes — это современный способ автоматизации операций с контейнерами Linux. Kubernetes помогает легко и эффективно управлять кластерами с контейнерами Linux в общедоступных, частных или гибридных облаках.

Red Hat® OpenShift® — это корпоративная платформа Kubernetes, которая предлагает группам разработки и эксплуатации общую платформу и набор инструментов в качестве основы для создания, развертывания и управления контейнерными приложениями в любой инфраструктуре, чтобы вы могли достичь своих целей ALM.
Если вы хотите в полной мере воспользоваться преимуществами гибкости и оперативности DevOps, ИТ-безопасность должна играть роль на протяжении всего жизненного цикла ваших приложений.
CI/CD обеспечивает постоянную автоматизацию и непрерывный мониторинг на протяжении всего жизненного цикла приложений, от этапов интеграции и тестирования до поставки и развертывания.
Инженер DevOps обладает уникальным сочетанием навыков и опыта, которое обеспечивает совместную работу, инновации и культурные сдвиги внутри организации.
Продукты
Интенсивная, целенаправленная резидентура с экспертами Red Hat, где вы научитесь использовать гибкую методологию и инструменты с открытым исходным кодом для работы над бизнес-задачами вашего предприятия.

Взаимодействия с нашими стратегическими консультантами, которые видят общую картину вашей организации, анализируют ваши проблемы и помогают вам преодолеть их с помощью комплексных и экономически эффективных решений.
Статьи по теме
Понимание DevOps
Облачная CI/CD на Red Hat OpenShift
Что такое автоматизация развертывания?
Что такое автоматизация DevOps?
Кто такой инженер DevOps?
- Что такое конвейер CI/CD?
- Что такое гибкая методология?
- Что такое управление жизненным циклом приложений (ALM)?
- Что такое сине-зеленое развертывание?
- Что такое CI/CD?
- Что такое непрерывная поставка?
- Что такое DevSecOps?
- Что такое GitOps?
- Что такое SRE (проектирование надежности объекта)?
Ресурсы
Автоматизация предприятия с помощью методологии DevOps
Оптимизация конвейеров CI/CD с помощью Red Hat Ansible Automation Platform
КОНТРОЛЬНЫЙ СПИСОК
5 способов, которыми инженеры по обеспечению безопасности могут помочь вам
02066 КОНТРОЛЬНЫЙ СПИСОК 90АНАЛИТИЧЕСКИЙ МАТЕРИАЛ
451 Отчет Research Pathfinder: Достижение интеллектуального DevOps
АНАЛИТИЧЕСКИЙ МАТЕРИАЛ
Развитие автоматизации DevOps
Получите больше подобного контента
Подпишитесь на нашу бесплатную рассылку Red Hat Shares.

Продолжить
404: Страница не найдена
Качество программного обеспеченияСтраница, которую вы пытались открыть по этому адресу, похоже, не существует. Обычно это результат плохой или устаревшей ссылки. Мы приносим свои извинения за доставленные неудобства.
Что я могу сделать сейчас?
Если вы впервые посещаете TechTarget, добро пожаловать! Извините за обстоятельства, при которых мы встречаемся. Вот куда вы можете пойти отсюда:
Поиск- Узнайте последние новости.
- Наша домашняя страница содержит последнюю информацию о качестве программного обеспечения.
- Наша страница «О нас» содержит дополнительную информацию о сайте, на котором вы находитесь, «Качество программного обеспечения».
- Если вам нужно, свяжитесь с нами, мы будем рады услышать от вас.
Просмотр по категории
Облачные вычисления
- Как выполнять и автоматизировать ротацию ключей в Azure Key Vault
Чтобы добавить еще один уровень безопасности, узнайте, как автоматически менять ключи в хранилище ключей Azure с помощью пошаговых инструкций.
.. - Развертывание Azure Key Vault и управление им с помощью Terraform
Terraform управляет ресурсами с помощью файлов конфигурации на облачных платформах. Следуйте этому пошаговому руководству, чтобы узнать, как …
- 6 разработчиков вариантов PaaS с открытым исходным кодом, о которых следует знать в 2023 году
PaaS с открытым исходным кодом — хороший вариант для разработчиков, которым нужен контроль над хостингом приложений и упрощенное развертывание приложений, но не…
Архитектура приложения
- Учебник по основным концепциям структуры команды разработчиков
Чтобы определить правильный размер команды разработчиков, менеджеры должны учитывать обязанности каждого члена и пути коммуникации, как …
- 10 учебных курсов для подготовки к сертификации по микросервисам
Хотя получить сертификат по архитектуре микросервисов не всегда просто, существует множество курсов, которые вы можете пройти, чтобы .
.. - Признаки антипаттерна «Золотой молот» и 5 способов его избежать
Антипаттерн «Золотой молот» может подкрасться к команде разработчиков, но есть способы его обнаружить. Изучайте знаки, а также некоторые…
ITОперации
- Что дальше: прогнозы, вызовы и ИТ-тенденции на 2023 год
По мере того, как организации стремятся решить проблему постоянной нехватки специалистов по эксплуатации и усложнения своей ИТ-среды, они будут инвестировать …
- Сравните Go и Python: в чем разница?
Golang и Python — универсальные, популярные языки, но у них есть несколько важных отличий, которые следует учитывать разработчикам…
- Dish Media меняет возможности наблюдения на Elastic Stack SaaS
С меньшим количеством инструментов и репозиториев данных для споров, а управление эластичным кластером передано на аутсорсинг SaaS, операционные группы Dish Media .
..
TheServerSide.com
- Как разработчики могут сохранять мотивацию при удаленной работе
Чувствуете, что потеряли преимущество в удаленной работе? Следуйте этим советам, чтобы оставаться энергичным, оттачивать свои навыки и напрягать …
- Скрам против Канбана: в чем разница?
Когда вы сравниваете Scrum и Kanban, вы понимаете, что у них столько же общего, сколько и различий. Здесь мы поможем вам выбрать …
- Различия между Java и TypeScript должны знать разработчики
Вы знаете Java? Вы пытаетесь изучить TypeScript? Вот пять различий между TypeScript и Java, которые сделают …
ПоискAWS
- AWS Control Tower стремится упростить управление несколькими учетными записями
Многие организации изо всех сил пытаются управлять своей огромной коллекцией учетных записей AWS, но Control Tower может помочь.


Вы можете нажимать на карточки или на кнопки «плюс» и «минус», чтобы обновить счетчики. На верхней панели у вас есть две кнопки: первая сбрасывает значения, а вторая открывает экран «Share» (Поделиться).
В этом состоянии пользователь, скорее всего, взаимодействует с активити.


i("PuppyCounter - MainActivity - onSaveInstanceState()")
// Save the dog count state
outState.putParcelable(STATE_DOG_COUNT, dogCount)
// Always call the superclass so it can save the view hierarchy state
super.onSaveInstanceState(outState)
}
extras?.run {
Timber.i("PuppyCounter - ShareActivity - readExtras()")
dogCount = getParcelable(EXTRA_DOG_COUNT) ?: DogCount()
}
На этом этапе жизненный цикл фрагмента подошел к концу.
i("PuppyCounter - MainFragment - onViewCreated()")
super.onViewCreated(view, savedInstanceState)
subscribeToViewModel()
findViews(view)
setupSmallDogViewsClickListeners(view)
setupMiddleDogViewsClickListeners(view)
setupBigDogViewsClickListeners(view)
}




Команды должны определить, в какой момент приложение больше не будет поддерживаться или станет доступна более новая версия.



..
..
..