Flutter runApp -- WidgetsFlutterBinding
前面我们分析学习了Flutter的项目结构,今天我们来看看main.dart里面的这样一段代码
void main() {
runApp(const MyApp());
}
Flutter 程序入口
main
方法一般是Flutter App的入口,它内部通过调用runApp方法应用整个Widget添加和运行。而且我们可以在不同的时机再次调用runApp
,比如在app 启动的时候因为数据加载等问题会有一个空白屏幕的时间。这个时候我们就可以通过多次调用runApp
来实现,简单的例子如下:
void main() {
runApp(const SplashScreen()); //
Future.delayed(Duration(seconds: 10), () {
runApp(const MyApp());
});
}
runApp
在外部通过调用runApp方法实现整个Widget效果,那么我们就去看看runApp方法的实现,如下:
void runApp(Widget app) {
WidgetsFlutterBinding.ensureInitialized()
..scheduleAttachRootWidget(app)
..scheduleWarmUpFrame();
}
这里可以看到上面有三行代码,分别代表了Flutter App启动的三个步骤:
WidgetsFlutterBinding
初始化(ensureInitialized()
),与Flutter Engine
进行通信。- 绑定根节点创建flutter 著名的三棵树(
scheduleAttachRootWidget(app)
)进行布局。 - 将布局出来的树进行渲染(
scheduleWarmUpFrame()
)
今天我们讲WidgetsFlutterBinding,不过也说WidgetsFlutterBinding,因为后面俩个自己学习的还是半桶水😭。
什么是WidgetsFlutterBinding?
官方的文档Widgets Binding,以及源代码里面注解有一句话是这样的:
The glue between the widgets layer and the Flutter engine.
你可以看到SystemChannels用于建立通信(MethodChannel)与引擎(其他语言环境的系统)。
mixin WidgetsBinding on BindingBase, ServicesBinding, SchedulerBinding, GestureBinding, RendererBinding, SemanticsBinding {
@override
void initInstances() {
super.initInstances();
_instance = this;
。。。。。。
SystemChannels.navigation.setMethodCallHandler(_handleNavigationInvocation);
。。。。。。
return true;
}());
}
我们看头部一行代码可以通过字面意思可以发现WidgetsFlutterBinding 继承自 BindingBase,也带有很多 XXXBinding。WidgetsFlutterBinding 将是 Widget 架构和 Flutter Engine 连接的核心桥梁,也是整个 Flutter 应用层的核心。通过 ensureInitialized()
方法我们可以得到一个全局单例 WidgetsFlutterBinding。
稍微解释一下各种Binding的作用。
- ServicesBinding:Flutter System 平台消息监听绑定类。即Platform与Flutter Layer通信相关服务,同时注册并监听应用生命周期回调。
- SchedulerBinding:Flutter 绘制调度器相关绑定类,调试统计绘制过程持续时间等编译模式下的操作。
- GestureBinding:Flutter Gesture事件绑定,处理屏幕事件分发和事件回调,其初始化方法的关键点是回调事件处理
_handlePointerDataPacket
函数被赋值给window的属性,以便window在接收到屏幕事件后调用,window的实例是 Framework Layer 和 Engine 桥接层用来处理屏幕事件。 - RendererBinding:引擎之间的渲染树和Flutter Binding类,内部重点是持有渲染树的根节点。
- SemanticsBinding:引擎之间的语义树和 Flutter Binding 类。
有时候我们会在发现有的app 在在运行应用程序之前先与 Flutter Engine 进行通信,所以要先将WidgetsFlutterBinding.ensureInitialized()
提前。
void main() {
WidgetsFlutterBinding.ensureInitialized();
runApp(const MyApp()); //
}
SystemChannels
在binding 初始化里面有这个一句话:
SystemChannels.navigation.setMethodCallHandler(_handleNavigationInvocation);
如果点击进去查看SystemChannels
的源码,可以看到内容使用了MethodChannel
(l方法通道)、EventChanne
(事件通道)、以及生命周期的东西。简单的用表格总结如下(可能不全。):
种类 | 作用 | Flutter Service |
---|---|---|
lifecycle | 生命周期 | widget |
navigation | 导航 | widget |
system | binding中使用 | widget |
accessibility | 辅助功能(如读取文本信息) | PlatformViews, Semantics |
platform | 系统设置(画面旋转等) | SemanticsService,RouteNotificationMessages etc. |
platform_views | 特定平台视图操作 | AndroidView, UiKitView |
skia | 图形引擎 | - |
keyEvent | 键输入 | RawKeyEvent |
textInput | 文本输入 | TextInput, AndroidView, UiKitView |
WidgetsBindingObserver
而关于 WidgetsBinding在Widget里面的具体使用,可以查看WidgetsBindingObserver源码,下面举一个简单的使用例子:
class _MyHomePageState extends State<MyHomePage> with WidgetsBindingObserver {
AppLifecycleState _state;
@override void initState() {
super.initState(); WidgetsBinding.instance.addObserver(this);
}
@override void dispose() { WidgetsBinding.instance.removeObserver(this);
super.dispose();
}
@override void didChangeAppLifecycleState(AppLifecycleState state){ print('state = $state');
}
}
转载自:https://juejin.cn/post/7031196891358429220