Activity
Activity
Представляет UI и функциональность, видимыe пользователю.
• если activity будет убита из-за low memory могут не вызваться killable-методы onStop
и onDestroy
(onPause
до версии 3.0)
• очистить бэкстек при создании activity: использовать флаг FLAG_ACTIVITY_CLEAR_TOP
, использовать вместе FLAG_ACTIVITY_CLEAR_TASK
и FLAG_ACTIVITY_NEW_TASK
Как пережить поворот экрана?
При повороте экрана активити уничтожается и создается заново. Вызываются коллбэки onPause()
, onStop()
, onSaveInstanceState()
, onDestroy()
– onCreate()
, onStart()
, onRestoreInstanceState()
, onResume()
. Чтобы сохранить состояние активити, вы должны переопределить метод onSaveInstanceState()
и положить данные в Bundle
. При реинициализации активити, Bundle с сохраненным состоянием передается в onCreate()
и в onRestoreInstanceState()
. Система вызывает onSaveInstanceState()
и onRestoreInstanceState()
только в том случае, когда необходимо сохранить состояние, например при повороте экрана или при убийстве активити для освобождения памяти. Данные коллбэки не вызываются, если пользователь выходит из активити нажав Back или если активити убивается вызовом finish()
. onSaveInstanceState()
вызывается после onStop()
на версии API ≥ 28. На API < 28 этот коллбэк вызывается перед onStop()
и нет гарантий до или после onPause()
. onRestoreInstanceState()
вызывается после onStart()
.
Как изменилось поведение onResume
и onPause
в Android 10?
В Android 10 добавлена поддержка foldables и девайсов с большим экраном. В связи с этим было изменено поведение коллбэков onResume() и onPause() в режиме multi-window. В Android 9 только активити, с которой взаимодействует пользователь, находилась в состоянии resumed, а все остальные активити на экране имели состояние paused. Начиная с Android 10, все видимые активити в режиме multi-window находятся в состоянии resumed. Это поведение называется multi-resume. Активити, с которой взаимодействует пользователь, называется topmost resumed. Для того, чтобы различать resumed и topmost resumed активити, в Android 10 добавлен коллбэк onTopResumedActivityChanged(isTopResumed: Boolean). Этот метод вызывается, когда активити получает или теряет состояние topmost.
Lifecycle
onCreate
Вызывается 1 раз, когда Activity
создается. Внутри него вызывается метод setContentView
.
onStart
Activity отрисована и видна пользователю.
onResume
Вызывается перед тем, как Activity
станет доступна для взаимодействия с пользователем.
onPause
Метод симметричный onResume
, пользователь больше не может взаимодействовать с Activity, но она остается видимой.
onStop
Метод симметричный onStart
, вызывается, когда Activity
больше не видна пользователю.
onDestroy
Метод симметричный onCreate
, вызывается перед тем, как Activity
будет уничтожена системой.
Launch Modes
standart
Режим запуска Activity по умолчанию в Android. В этом режиме каждый раз, когда Activity запускается, создается новый экземпляр этой Activity, и каждый новый экземпляр помещается в стек задач. При этом Activity может быть создано несколько раз, даже если уже существует экземпляр этой Activity в стеке. Каждый новый экземпляр Activity в режиме standard получает уникальный task и back stack, что позволяет сохранить состояние и историю переходов, обеспечивая независимость между различными экземплярами Activity.
singleTop
Режим запуска Activity, при котором только один экземпляр Activity может быть в стеке задач. Если Activity с singleTop уже находится на вершине стека, новая попытка её запуска не создаст новый экземпляр, а вызовет метод onNewIntent(). Если Activity не на вершине стека, будет создан новый экземпляр.
<activity
android:name=".YourActivity"
android:launchMode="singleTop">
</activity>
singleTask
Режим запуска Activity, при котором в одной задаче может существовать только один экземпляр Activity. Если Activity с singleTask уже существует, она будет показана, и все Activity в текущем стеке выше её будут удалены; если нет, она будет создана в новой задаче.
<activity
android:name=".YourActivity"
android:launchMode="singleTask">
</activity>
singleInstance
Устанавливает, что Activity будет существовать только в одном экземпляре в своей собственном, отдельном стеке задач (task). Это означает, что если такая Activity уже существует, то новая задача не создаст её экземпляр, а вместо этого вернёт существующий экземпляр.
<activity
android:name=".YourActivity"
android:launchMode="singleInstance">
</activity>
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 в стек задач, который будет запущен после текущей активности. Это позволяет создать цепочку активностей и правильно управлять их порядком.
addNextIntentWithParentStack
Позволяет добавить Intent в стек задач с учетом родительской активности. Этот метод гарантирует, что при возврате к предыдущим экранам будет создан правильный стек задач, включая все родительские активности.
ActivityManager
Системный сервис в Android, который управляет жизненным циклом активностей и задач, а также отслеживает состояние процессов в системе. ActivityManager отслеживает все активные, видимые и фоновые активности на устройстве.
val activityManager = getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
getRunningTasks
Возвращает список задач, которые в настоящее время запущены. Можно указать максимальное количество задач, которые нужно вернуть.
val runningTasks = activityManager.getRunningTasks(10)
getRunningAppProcesses
Возвращает список всех запущенных процессов в системе.
val runningAppProcesses = activityManager.runningAppProcesses
getRecentTasks
Возвращает список недавних задач, которые можно открыть из недавнего меню приложений.
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.appTasks
getLauncherActivities
Возвращает список активностей, которые могут быть запущены из лаунчера.
val launcherActivities = activityManager.launcherActivities
OnBackPressedDispatcher
Управляет обработкой нажатия кнопки “Назад” (Back) в приложении. Позволяет разным частям приложения регистрировать свои обработчики, которые будут вызваны при нажатии кнопки. Пришел на замену методу onBackPressed
.
class MainActivity: AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// Регистрируем обработчик нажатия кнопки "Назад"
onBackPressedDispatcher.addCallback(this, object: OnBackPressedCallback(true) {
override fun handleOnBackPressed() {
// Логика при нажатии кнопки "Назад"
println("Кнопка 'Назад' нажата")
}
})
}
}
Android Activity. Вопросы на собесе
- Как пережить поворот экрана? (Смену конфигурации)
- Какие методы жизненного цикла Activity вызываются при переходе на следующую Activity?
• Переходим вперед:
onPause()
→onStop()
• Возвращаемся обратно:
onStart()
→onResume()
- Какие методы жизненного цикла 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()
- Как изменилось поведение onResume и onPause в Android 10?
В Android 10 методы
onResume()
иonPause()
теперь учитывают многозадачность:onResume()
вызывается, когда Activity становится активной, даже если она не на переднем плане, аonPause()
вызывается, когда Activity теряет фокус, но может оставаться видимой.
- Как запустить стек из нескольких Activity?
Через
TaskStackBuilder
в виде стека одним вызовом.
- Как запустить Activity в отдельном процессе?
Указать атрибут
android:process
в манифесте для этой Activity.
- Перечисли все Launch modes?
standart
singleTop
singleTask
singleInstance
- Чем Activity отличается от Fragment?
Мы легко можем управлять стеком фрагментов. Со стеком активностей возникают проблемы: мы не можем гарантировать их порядок, активити может создастся по интенту другим приложением.
- Если запустить Activity2 которая частично перекрывает Activity1, какие коллбэки вызовутся у Activity1?
onPause()
- Жизненный цикл Activity?
onCreate()
→onStart()
→onResume()
→onPause()
→onStop()
→onDestroy()
- Когда onDestroy вызовется без onPause и onStop?
finish()
вonCreate()
- Можно ли создать приложение без Activity?
• Да, можно. (Приложение обои. Будить через
BroadcastReceiver
стартовать сервис)• Нет, у приложения всегда должна быть хотя бы одна активити.