Любое приложение имеет жизненный цикл. Обнаружение изменений состояния этого жизненного цикла может быть необходимо в следующих ситуациях:
Ниже представлена схема, которая демонстрирует поведение приложения, когда его установил пользователь.
Flutter имеет 5 состояний приложения.
Возобновленное состояние (resumed)
В этом состоянии приложение видно пользователю и активно (на экране). Можно отлавливать события с помощью слушателя AppLifycycleListener - onInactive.
Неактивное состояние (inactive)
В этом состоянии приложение может по-прежнему быть видимым для пользователя (например, в фоне), но оно не получает вводимые пользователем данные и может перейти в состояние паузы в любое время.
На Android это может произойти, когда фокус переключается на другое действие, например телефонный звонок, системный диалог, приложение с разделенным экраном или всплывающее окно. В iOS это может произойти при телефонном звонке, входе в переключатель приложений, ответе на запрос TouchID. Здесь также можно воспользоваться методом onResume (при восстановлении работы) и onHide (при скрытии приложения) для обработки событий.
Скрытое состояние (hidden)
Все представления приложения скрыты, либо потому, что приложение вот-вот будет приостановлено (на iOS и Android), либо потому, что оно свернуто или помещено на рабочий стол, который больше не отображается. Тут работают методы onPause (переход в состояние паузы) и onShow (переход в inactive).
Состояние паузы (paused)
В этом состоянии приложение не видно пользователю и оно не отвечает на вводимые пользователем данные и работает в фоновом режиме. Методы: onRestart (переход в перезапуск) и onDetach (переход в отделенное состояние).
Отделенное состояние (detached)
Приложение вообще не запущено. Возможные условия: когда экран инициализируется впервые (в процессе присоединения состояния) или уничтожается из Navigator.pop() (например, нажатие кнопки «Назад» на домашней странице приложения).
Flutter предоставляет несколько методов, которые вызываются переходами приложения между различными состояниями жизненного цикла. Эти методы можно переопределить для обработки событий жизненного цикла приложения.
didChangeAppLifecycleState: этот метод вызывается всякий раз, когда приложение переходит между состояниями жизненного цикла. Он получает AppLifecycleState объект, который обозначает новое состояние. Можно использовать этот метод при переходе приложения между состояниями.
dispose: этот метод вызывается, когда объект будет уничтожен. Можно использовать этот метод для очистки любых ресурсов, которые использует ваше приложение.
Вот несколько примеров использования этих методов для обработки событий жизненного цикла приложения:
class _AppLifeCycleExampleState extends State<AppLifeCycleExample>
with WidgetsBindingObserver {
AppLifecycleState? _appLifecycleState;
@override
void initState() {
super.initState();
WidgetsBinding.instance.addObserver(this);
}
@override
void dispose() {
WidgetsBinding.instance.removeObserver(this);
super.dispose();
}
@override
void didChangeAppLifecycleState(AppLifecycleState state) {
super.didChangeAppLifecycleState(state);
setState(() {
_appLifecycleState = state;
});
}
В этом примере мы используем didChangeAppLifecycleState метод для обновления состояния приложения. Также используем dispose метод для удаления observer’a, добавленного в initState метод.
Другой способ отслеживания жизненного цикла:
Пример кода:
late final AppLifecycleListener _listener;
final ScrollController _scrollController = ScrollController();
final List _states = [];
late AppLifecycleState? _state;
@override
void initState() {
super.initState();
_state = SchedulerBinding.instance.lifecycleState;
_listener = AppLifecycleListener(
onShow: () => _handleTransition('show'),
onResume: () => _handleTransition('resume'),
onHide: () => _handleTransition('hide'),
onInactive: () => _handleTransition('inactive'),
onPause: () => _handleTransition('pause'),
onDetach: () => _handleTransition('detach'),
onRestart: () => _handleTransition('restart'),
// This fires for each state change. Callbacks above fire only for
// specific state transitions.
onStateChange: _handleStateChange,
);
if (_state != null) {
_states.add(_state!.name);
}
}
@override
void dispose() {
_listener.dispose();
super.dispose();
}
void _handleTransition(String name) {
setState(() {
_states.add(name);
});
// обработка каждого перехода
}
void _handleStateChange(AppLifecycleState state) {
setState(() {
_state = state;
});
}
Здесь инициализируем слушатель со всеми методами для обработки состояния приложения.
Отслеживание состояния жизненного цикла приложения – очень полезная “история”, так как задачи, связанные с жизненным циклом, могут быть самыми разными. Кто знает, с каким кейсом вам придется столкнуться на практике :)
Например, обработка пуш-уведомлений, обновление приложения или же конкретный кейс: когда добавляешь какие-либо товары в корзину и при открытии приложения из состояния, отличного от resumed, нужно провалидировать эту самую корзину (проверить товары на доступность).
Спасибо за внимание! Надеюсь, что статья была полезна. Подписывайтесь на Flutter.Много и делитесь своим опытом работы с жизненным циклом приложения в комментариях.