
Activity
Activity
Основной компонент Android, представляющий экран приложения. Она управляет UI, жизненным циклом и взаимодействием с пользователем.
class MainActivity: AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
override fun onStart() {
super.onStart()
}
override fun onResume() {
super.onResume()
}
override fun onPause() {
super.onPause()
}
override fun onStop() {
super.onStop()
}
override fun onDestroy() {
super.onDestroy()
}
}onCreate
Вызывается при создании Activity. В нём задаётся интерфейс и начальная логика.
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}onStart
Вызывается, когда Activity становится видимой для пользователя.
override fun onStart() {
super.onStart()
dataObserver.startObserving()
}onResume
Вызывается, когда Activity переходит в активное состояние и готова взаимодействовать с пользователем.
override fun onResume() {
super.onResume()
startRefreshingData()
}onPause
Вызывается, когда Activity уходит на второй план, но всё ещё частично видима.
override fun onPause() {
super.onPause()
pauseAnimations()
}onStop
Вызывается, когда Activity перестаёт быть видимой.
override fun onStop() {
super.onStop()
dataObserver.stopObserving()
}onDestroy
Вызывается перед уничтожением Activity.
override fun onDestroy() {
super.onDestroy()
cleanupResources()
}isFinishing
Используется для проверки, находится ли активность в процессе завершения. Он возвращает true, если активность была запущена для завершения (например, из-за вызова finish() или по завершению жизненного цикла Activity), и false, если активность все еще активно работает. Вы можете использовать isFinishing() перед выполнением операций, которые требуют, чтобы активность была активна, чтобы избежать потенциальных ошибок, связанных с обращением к UI, если активность уже завершена.
override fun onPause() {
super.onPause()
if (!isFinishing) {
// Выполняем действия только если Activity не завершается
}
}Launch Modes
standart
Режим запуска Activity по умолчанию в Android. В этом режиме каждый раз, когда Activity запускается, создается новый экземпляр этой Activity, и каждый новый экземпляр помещается в стек задач. При этом Activity может быть создано несколько раз, даже если уже существует экземпляр этой Activity в стеке. Каждый новый экземпляр Activity в режиме standard получает уникальный task и back stack, что позволяет сохранить состояние и историю переходов, обеспечивая независимость между различными экземплярами Activity.
<activity
android:name=".MainActivity"
android:launchMode="standart" />singleTop
Режим запуска Activity, при котором только один экземпляр Activity может быть в стеке задач. Если Activity с singleTop уже находится на вершине стека, новая попытка её запуска не создаст новый экземпляр, а вызовет метод onNewIntent(). Если Activity не на вершине стека, будет создан новый экземпляр.
<activity
android:name=".MainActivity"
android:launchMode="singleTop" />singleTask
Режим запуска Activity, при котором в одной задаче может существовать только один экземпляр Activity. Если Activity с singleTask уже существует, она будет показана, и все Activity в текущем стеке выше её будут удалены; если нет, она будет создана в новой задаче.
<activity
android:name=".MainActivity"
android:launchMode="singleTask" />singleInstance
Устанавливает, что Activity будет существовать только в одном экземпляре в своей собственном, отдельном стеке задач (task). Это означает, что если такая Activity уже существует, то новая задача не создаст её экземпляр, а вместо этого вернёт существующий экземпляр.
<activity
android:name=".MainActivity"
android:launchMode="singleInstance" />singleInstancePerTask
Когда активность запускается в режиме singleInstancePerTask, система создает единственный экземпляр этой Activity для каждой задачи. Это означает, что если активность уже существует в другой задаче, новый экземпляр не будет создан. Вместо этого пользователь будет перенаправлен к существующему экземпляру. В отличие от других режимов запуска (например, singleTask), этот режим обеспечивает, что Activity всегда будет единственной в своей задаче, и только одна задача может содержать этот экземпляр. Если Activity вызывается из другой задачи, она будет перемещена в фокус, а не создана заново.
• Добавлен в Android 12 (API 31).
<activity
android:name=".MainActivity"
android:launchMode="singleInstancePerTask" />taskAffinity
Определяет, к какой задаче (task) принадлежит активность. По умолчанию все активности приложения имеют одинаковую задачу, но с помощью taskAffinity можно задать для активности принадлежность к другой задаче. Task (Задача) — это стек активностей, с которыми взаимодействует пользователь. Если активность имеет другую taskAffinity, она может быть запущена в отдельной задаче или присоединиться к задаче другого приложения с таким же значением taskAffinity. Это полезно, когда нужно контролировать, как активности взаимодействуют с задачами и как они отображаются в списке последних приложений.
• Работает в связке с launchMode активности (например, singleTask, singleTop). Например, если taskAffinity изменён, а launchMode задан как singleTask, активность будет запускаться в своей задаче и перезапускаться, если она уже существует.
• Хорошее объяснение на StackOverflow.
<activity
android:name=".MainActivity"
android:taskAffinity="" />
<activity
android:name=".SettingsActivity"
android:taskAffinity="com.example.differenttask" />TaskStackBuilder
Позволяет создавать и управлять стеком задач для запуска активностей. Он помогает организовать задачи и их историю, чтобы обеспечить правильное поведение навигации при запуске новых активностей. TaskStackBuilder упрощает создание и запуск стека активностей, который будет отображаться в правильном порядке, когда пользователь возвращается к предыдущим активностям.
// Создаем TaskStackBuilder для запуска нового Activity
val stackBuilder = TaskStackBuilder.create(context)
// Добавляем Intent для нового Activity
stackBuilder.addNextIntentWithParentStack(newIntent)
// Запускаем Activity
stackBuilder.startActivities()addNextIntent
Добавляет новый Intent в back stack без учета родительских экранов.
addNextIntentWithParentStack
Добавляет новый Intent в back stack с учетом иерархии родительских экранов.
ActivityManager
Системный сервис в Android, который управляет жизненным циклом активностей и задач, а также отслеживает состояние процессов в системе. ActivityManager отслеживает все активные, видимые и фоновые активности на устройстве.
val activityManager = getSystemService(Context.ACTIVITY_SERVICE) as ActivityManagergetRunningTasks
Возвращает список задач, которые в настоящее время запущены. Можно указать максимальное количество задач, которые нужно вернуть.
val runningTasks = activityManager.getRunningTasks(10)getRunningAppProcesses
Возвращает список всех запущенных процессов в системе.
val runningAppProcesses = activityManager.runningAppProcessesgetRecentTasks
Возвращает список недавних задач, которые можно открыть из недавнего меню приложений.
val recentTasks = activityManager.getRecentTasks(10, ActivityManager.RECENT_IGNORE_UNAVAILABLE)getRunningServices
Возвращает список всех запущенных служб.
val runningServices = activityManager.getRunningServices(10)getMemoryInfo
Заполняет объект ActivityManager.MemoryInfo информацией о текущем состоянии памяти.
val memoryInfo = ActivityManager.MemoryInfo()
activityManager.getMemoryInfo(memoryInfo)getProcessMemoryInfo
Возвращает информацию о потреблении памяти для процессов с указанными идентификаторами процессов (PID).
val processMemoryInfo = activityManager.getProcessMemoryInfo(intArrayOf(pid))killBackgroundProcesses
Завершает все фоновые процессы, связанные с указанным пакетом.
activityManager.killBackgroundProcesses("com.example.myapp")getAppTasks
Возвращает список задач, связанных с текущими приложениями.
val appTasks = activityManager.appTasksgetLauncherActivities
Возвращает список активностей, которые могут быть запущены из лаунчера.
val launcherActivities = activityManager.launcherActivitiesOnBackPressedDispatcher
Управляет обработкой нажатия кнопки «Назад» (Back) в приложении. Позволяет разным частям приложения регистрировать свои обработчики, которые будут вызваны при нажатии кнопки. Пришел на замену методу onBackPressed.
class MainActivity: AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// Регистрируем обработчик нажатия кнопки "Назад"
onBackPressedDispatcher.addCallback(this, object: OnBackPressedCallback(true) {
override fun handleOnBackPressed() {
// Логика при нажатии кнопки "Назад"
println("Кнопка 'Назад' нажата")
}
})
}
}Вопросы на собесе (33)
Lifecycle (14)
- Жизненный цикл Activity?
onCreate()→onStart()→onResume()→onPause()→onStop()→onDestroy()
- Какие методы жизненного цикла Activity вызываются при переходе на следующую Activity?
• Переходим вперед:
onPause()→onStop()• Возвращаемся обратно:
onStart()→onResume()
- В какой момент жизненного цикла Activity виден экран?
onStart()
- Какие методы жизненного цикла Activity вызываются при отображении DialogFragment?
Жизненный цикл не изменяется.
- Какие методы жизненного цикла Activity вызываются при отображении/закрытии permission dialog?
onPause()↔onResume()
- Какие методы жизненного цикла Activity вызываются при переходе в task manager (recent menu)?
Жизненный цикл не изменяется.
- Какие методы жизненного цикла Activity вызываются при смахивании приложения?
onPause()→onStop()→onDestroy()
- Какие методы жизненного цикла Activity вызываются при сворачивании/разворачивании приложения?
• При сворачивании:
onPause()→onStop()• При разворачивании:
onStart()→onResume()
- Какие методы жизненного цикла Activity вызываются при смене ориентации экрана (изменении конфигурации)?
• Activity пересоздается:
onPause()→onStop()→onDestroy()→onCreate()→onStart()→onResume()• При сохранении состояния:
onPause()→onStop()→onSaveInstanceState()→onDestroy()→onCreate()→onStart()→onRestoreInstanceState()→onResume()
- Если запустить Activity2 которая частично перекрывает Activity1, какие коллбэки вызовутся у Activity1?
onPause()
- Когда onDestroy вызовется без onPause и onStop?
finish()вonCreate()
- В каком случае вызов onDestroy() не гарантирован?
В случае внезапного завершения процесса системы, например, если система убивает приложение для освобождения ресурсов, когда недостаточно памяти. В таких ситуациях система может не вызвать методы жизненного цикла, включая
onDestroy().
- Как изменилось поведение onResume и onPause в Android 10?
В Android 10 добавлена поддержка foldables и изменено поведение коллбэков
onResume()иonPause()в режиме multi-window: все видимые активити находятся в состоянии resumed, а Activity, с которой взаимодействует пользователь, называется topmost resumed. Введен коллбэкonTopResumedActivityChanged(isTopResumed: Boolean)для различия между resumed и topmost resumed Activity.
- В каком из случаев вызов onDestroy() в Activity не гарантирован?
• Переворот экрана.
• Вызов метода
finish().• Приложение свернуто, система ”убила” процесс приложения.
- Жизненный цикл Activity?
Launch Modes (8)
- Какие есть Launch Modes у Activity?
standartsingleTopsingleTasksingleInstance
- Для чего нужно задавать параметр launchMode у Activity?
Параметр
launchModeзадает, как будет вести себя новаяActivityпри запуске, управляя созданием экземпляров в стеке задач и предотвращая дублирование.
- Как работает launchMode SingleTop?
SingleTopзапускаетActivityтолько в том случае, если она не находится на вершине стека. ЕслиActivityуже открыта, система вызывает методonNewIntent()существующего экземпляра, передавая ему новые намерения, что позволяет обновить данные без создания нового экземпляра.
- Как работает launchMode SingleInstance?
SingleInstanceсоздает уникальный экземплярActivityв своем собственном стекe задач. Если такаяActivityуже существует, при запуске вызоветсяonNewIntent().
- Есть стек из Activity A-B-C-A-B, запускаем Activity C c launchMode SingleTop, что произойдет в системе?
У
ActivityC вызовется методonNewIntent().
- Ты находишься внутри Activity A и опять вызываешь Activity A c launch mode SingleTop, что произойдет в Activity A?
Вместо создания нового экземпляра будет переиспользован текущий, и вызовется метод
onNewIntent().
- Есть Activity А, ты запустил Activity B с launch mode SingleTask и в ней произошел краш, что произойдет с приложением и что увидит юзер?
Приложение завершится, и пользователь увидит системное сообщение о том, что приложение остановилось. Activity A также будет уничтожена вместе с приложением.
- Эффект какого из launch mode Activity описан ниже? Если экземпляр Activity уже существует на вершине текущего Task, новый экземпляр не будет сгенерирован, а новые данные для Activity будут оправлены через onNewlntent().
•
singleTask•
singleTop•
singlelnstance•
standard
- Какие есть Launch Modes у Activity?
Другие (11)
- Как сделать Activity главной?
Указать для нее в
AndroidManifestintent-фильтр сactionMAIN иcategoryLAUNCHER.
- Что будет если сделать 2 Activity главными?
Обе будут отображаться в списке приложений, и пользователь сможет выбрать, какую из них запустить.
- Как пережить поворот экрана? (Смену конфигурации)
• Переопределить
onSaveInstanceState(Bundle outState)и восстановить вonCreate().• Использовать
ViewModelдля сохранения данных.• Добавить
configChangesв манифест (не рекомендуется).
- Есть ли смысл сохранять данные если поддерживаем только портретную ориентацию?
Да. В приложении может произойти сбой. Существуют другие способы изменения конфигурации (смена локали).
- Как запустить стек из нескольких Activity?
Через
TaskStackBuilderв виде стека одним вызовом.
- Как запустить Activity в отдельном процессе?
Указать атрибут
android:processв манифесте для этойActivity.
- Чем Activity отличается от Fragment?
Мы легко можем управлять стеком фрагментов. Со стеком активностей возникают проблемы: мы не можем гарантировать их порядок, активити может создастся по интенту другим приложением.
- Если не вызовем setContentView или поместим туда null что увидим?
Цвет установленный в
windowBackground.
- Как запустить приложение без Activity?
Через
BroadcastReceiver, который реагирует на системные события (например, загрузку устройства), или черезService, запущенный при старте системы. В этом случае интерфейса у приложения не будет, но фоновые задачи могут выполняться.
- Как закрыть сразу n активити в стеке?
Удалить все
Activityвыше запущенной в стеке можно через флагflags = Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_NEW_TASK.
- Можно ли создать приложение без Activity?
• Да, можно. (Приложение Android WebView. Системный сервис для просмотра web-страниц)
• Нет, у приложения всегда должна быть хотя бы одна активити.
- Как сделать Activity главной?