监听Flutter App切换前后台,支持单页面和全局
开发时候,我们会通过App是否在前台运行做一些操作,我们可以监听下面两种情况:
- 全局监听:不管在哪个页面,只要App里面切换了前后台就会触发,常用于数据埋点等
- 单页面监听:只有在某个页面进行App切换前后台才会触发,常用于页面数据刷新等
App状态以及流转
App生命周期状态有下面的几个:
1、resumed
App是可见状态并且接受用户的交互。
2、inactive
App不是激活状态并且不再接受用户的交互,下一步将会切换到paused状态,inactive状态持续时间很短。
在Android上,下面的行为会让App进入到inactive状态
- 关闭屏幕
- 有电话打进来
- 展示系统对话框
在iOS上,下面的行为会让App进入到inactive状态
- 关闭屏幕
- 有电话打进来
- 应用程序在响应Touch ID或者Face ID等
- 进入到应用切换器或者控制中心
3、paused
应用程序切换到了后台,用户不可见不再接受用户交互,在当前状态时候,Flutter会做一些优化,例如停止执行PlatformDispatcher.onBeginFrame 和 PlatformDispatcher.onDrawFrame来节能。
4、detached
Flutter没有视图展示的时候的状态,一般会在App退出的时候执行。
各个操作导致的状态流转;
全局监听状态变更
针对于全局监听,我们可以使用SystemChannels去实现,将下面的代码放置在runApp之前即可:
SystemChannels.lifecycle.setMessageHandler((msg) async {
debugPrint('SystemChannels> $msg');
// msg是个字符串,是下面的值
// AppLifecycleState.resumed
// AppLifecycleState.inactive
// AppLifecycleState.paused
// AppLifecycleState.detached
return msg;
});
runApp(MyApp());
单页面监听状态变更
针对于单页面监听,我们需要用到StatefulWidget和WidgetsBindingObserver,为什么不能使用Stateless组件呢?因为Stateless组件没有完整的生命周期,无法注册事件监听;
WidgetsBindingObserver 会为组件添加一系列生命周期,官网文档给出了说明
对于App状态改变的生命周期,我们使用didChangeAppLifecycleState;
void didChangeAppLifecycleState(AppLifecycleState state) { }
具体实现如下所示
import 'package:flutter/material.dart';
class TestLifecycle extends StatefulWidget {
const TestLifecycle({super.key});
@override
State<TestLifecycle> createState() => _TestLifecycleState();
}
class _TestLifecycleState extends State<TestLifecycle>
with WidgetsBindingObserver {
@override
void initState() {
super.initState();
WidgetsBinding.instance.addObserver(this);
}
@override
void didChangeAppLifecycleState(AppLifecycleState state) {
super.didChangeAppLifecycleState(state);
if (state == AppLifecycleState.resumed) {
print("切换到了前台");
} else if (state == AppLifecycleState.paused) {
print("切换到了后台");
}
}
@override
void dispose() {
WidgetsBinding.instance.removeObserver(this);
super.dispose();
}
@override
Widget build(BuildContext context) {
return Container();
}
}