现在,flutter这门技术已经算是逐渐走向成熟,大大小小的互联网公司不少都开始投入使用。还没有上手的移动开发们可以放心上手了,毕竟好不好用,也只有用了才知道。
学习一门知识最好的办法就是学以致用,并总结出自己的方法论。也只有真正理解了,才能总结出有用的经验。下面是知乎一个大佬的学习经验分享,欢迎大家一起探讨学习。
大佬原文地址:https://zhuanlan.zhihu.com/p/388724188
调用图
我们用下面的例子来分析Flutter启动所做的事情
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Container();
}
}
初始化Binding
runApp
void runApp(Widget app) {
WidgetsFlutterBinding.ensureInitialized()
..scheduleAttachRootWidget(app)
..scheduleWarmUpFrame();
}
在runApp
中,我们会调用WidgetsFlutterBinding.ensureInitialized()
来初始化Binding
。
Binding
Binding
是一系列单例,在启动的时候初始化,其中包括了WidgetsFlutterBinding
、BindingBase
、GestureBinding
、SchedulerBinding
、ServicesBinding
等,下面来分析它们的作用
- BindingBase: 是所有类的基类,负责初始化其它类、初始化一些Native相关的信息(如平台是Android还是iOS)、注册基本的Native事件(如热更新、退出)
- GestureBinding: 提供
window.onPointerDataPacket
回调,接受Native事件,负责事件转换及分发 - SchedulerBinding: 使用了
window.scheduleFrame
来通知Native及使用window.onBeginFrame
和window.onDrawFrame
回调来接收消息,主要是负责通知Native在下一侦的事件下发与事件注册,当我们调用setState后,就会触发此类的方法,等待事件下发后进行渲染 - ServicesBinding: 使用
window.onPlatformMessage
回调,负责通道相关的初始化及通信相关的处理 - PaintingBinding: 与绘制相关的函数绑定,还处理一些图片渲染相关的缓存
- SemanticsBinding: 注册平台相关的辅助函数
- RendererBinding: 初始化
PipelineOwner
、renderView
、onMetricsChanged
、onTextScaleFactorChanged
、onPlatformBrightnessChanged
、onSemanticsEnabledChanged
onSemanticsAction
等,用于监听并处理平台渲染相关如字体、状态栏改变时的事件,是渲染输与Flutter engine沟通的桥梁 - WidgetsBinding: 初始化
BuildOwner
,注册window.onLocaleChanged
、onBuildScheduled
等回调。它是Flutter widget层与engine的桥梁。
渲染树的构建
attachRootWidget
[-> packages/flutter/lib/src/widgets/binding.dart]
void attachRootWidget(Widget rootWidget) {
_readyToProduceFrames = true;
_renderViewElement = RenderObjectToWidgetAdapter<RenderBox>(
container: renderView,
debugShortDescription: '[root]',
child: rootWidget,
).attachToRenderTree(buildOwner!, renderViewElement as RenderObjectToWidgetElement<RenderBox>?);
}
上面会先初始化一个RenderObjectToWidgetAdapter
,它是一个特殊的Widget
,主要用Flutter树根节点的初始化,其中传了一个renderView
,上面提到了是在RendererBinding初始化时就已经初始化了,它是根RenderObject
节点,rootWidget
就是我们runApp时传入的Widget
。
后面调用了attachToRenderTree
会开始一系列的树构建
attachToRenderTree
[-> packages/flutter/lib/src/widgets/binding.dart]
RenderObjectToWidgetElement<T> attachToRenderTree(BuildOwner owner, [ RenderObjectToWidgetElement<T>? element ]) {
// 如果element==null执行,第一次渲染element一定为null
if (element == null) {
owner.lockState(() {
// 调用createElement创建Element