我正在参加「掘金·启航计划」
runApp入口
在Flutter
的main
函数创建根组件作为入参初始化了WidgetsFlutterBinding
。
WidgetsFlutterBinding
WidgetsFlutterBinding
是一个特殊类继承了BindingBase
又混入了各种Binding
。而混入with
也是Dart
比较特殊的语法糖同时也是WidgetsFlutterBinding
类特别之处。
WidgetsFlutterBinding
实现比较简单只做了初始化功能,实例化单例对象WidgetsBinding
。(暂且先不关心它)先分别介绍一下每个Binding的职责。
WidgetsBinding
initInstances
初始化函数大致可知WidgetsBinding
主要职责是负责脏节点刷新以及平台的本地化、特性变化和帧刷新等监听工作,脏节点组件更新由BuildOwner
负责完成。
RendererBinding
initInstances
初始化函数中创建了PipelineOwner
、RenderView
,其主要职责是负责Flutter
的UI
渲染工作,PipelineOwner
并是负责渲染的重要类。
此外RenderingFlutterBinding
类是类似WidgetsFlutterBinding
带有初始化方法ensureInitialized
实例化对象。
SemanticsBinding
SemanticsBinding
主要处理平台上辅助服务事件,所负责职责比较少。
PaintingBinding
PaintingBinding
主要职责管理图片缓存和着色器预热,分别由ImageCache
和ShaderWarmUp
管理。
ServicesBinding
ServicesBinding
主要职责创建二进制通信服务、平台软键盘功能、平台系统消息通信和生命周期以及平台插件方法等注册。
SystemChannels.lifecycle.setMessageHandler(_handleLifecycleMessage)
负责生命周期SystemChannels.system.setMessageHandler((dynamic message) => handleSystemMessage(message as Object))
负责系统信息监听(例如低内存警告memoryPressure
)_initKeyboard()
负责软硬键盘输入信息SystemChannels.platform.setMethodCallHandler(_handlePlatformMessage)
负责平台方法调用
SchedulerBinding
SchedulerBinding
负责任务调度处理各种类型任务调度时机,之前讲到的三辆马车运作就是在该类中实现的。其主要能力是和平台帧交互,调度平台帧等待平台的开始帧和绘制帧来驱动三辆马车运作起来从而达到刷新UI和驱动任务的作用。
_timingsCallbacks
用于检测GPU耗时检测handleAppLifecycleStateChanged
控制帧状态是否可用(后台情况下不刷新)_persistentCallbacks
、_postFrameCallbacks
以及_transientCallbacks
三个回调分别代表瞬时回调、帧结束回调和动画回调。
GestureBinding
GestureBinding
负责手势操作处理对Flutter
事件分发管理。
_handlePointerDataPacket
接受平台发起事件数据包_pendingPointerEvents
是事件数据包队列_flushPointerEventQueue
循环_pendingPointerEvents
队列,只要队列不为空并做处理handlePointerEvent
会通过_handlePointerEventImmediately
处理指针事件PointerEvent
得到HitTestResult
结果- 通过
dispatchEvent
将HitTestResult
结果分发。
PS:事件分发也是
Flutter
开发中重要一环,后续可以单独展开说说
mixin & with & on
在WidgetsFlutterBinding
类实现上可看到with
各种xxxBinding
,此外其他Binding
是mixin
且又on
其他Binding
,这就是dart
特殊语法糖:混入类。
Mixin
是一种在多个类层次结构中重用类代码的方法。Mixin
支持混入多个对象。- 用
Mixin
修饰对象不能有构造函数,因此无法直接实例化对象。(除非该对象是Class
就不能是Mixin
) on
关键字主要为了限制Mixin
,例如Mixin
类型B
是on
了A
类,若C
希望with
B就必须继承A
类;Mixin
类型B
是on了Mixin
类型A
,若C
希望with
B同样需要Mixin
类型A
并且A
必须在B
的前面
如下是mixin
、on
、with
使用场景实操来演示最终结果展示。
class A {
void todo() {
print("<> todo A");
}
}
mixin AA on A {
@override
void todo() {
super.todo();
print("<> todo AA");
}
void todo2(){
print("<> todo2 AA");
}
}
mixin AAA on A{
void todo2(){
print("<> todo2 AAA");
}
@override
void todo() {
super.todo();
print("<> todo AAA");
}
}
mixin AAAS on AAA{
@override
void todo2(){
super.todo();
print("<> todo2 AAAS");
}
}
demo1
BB
继承A
并且with
了AAA
和AA
当执行todo2()
时执行AA
的todo2()
。由于with
特性是找到最远混入对象因此执行输出是"<> todo2 AA"
,若with
是 AA
,AAA
那么执行方法就变成是AAA
的todo2()
输出变为"<> todo2 AAA"
。
class BB extends A with AAA,AA {
@override
void todo() {
super.todo();
print("<> todo BB");
}
}
void main(){
BB bb = BB();
bb.todo2();//<> todo2 AA
}
因此可以知with
并不是继承(可能容易理解为继承关系)with
的每个对象同一个方法名是相互隔离,而被with
对象调用了哪个方法名取决于with
的最后一个是哪个。
demo2
CC
直接with
到AAAS
是非法的,因为AAAS
是on
了AAA
,且AAA
还on
了A
。
class CC with AAAS{
void todo() {
super.todo();
print("<> todo CC");
}
}
因此CC
需要继承A
然后依次with
到AAA
和AAAS
(顺序不能乱),另外CC
也可以不继承A
同样采用with
也是可以的,位置同样重要必须在AAA
和AAAS
前面。
class CC extends A with AAA,AAAS{
void todo() {
super.todo();
print("<> todo CC");
}
}
回顾
再看Flutter
的Binding
设计就很好运用了with
思路,每个Binding
都有各自职责虽然每个职责又无法做到绝对独立,但每个Binding
存在着关联系,如果设计采用继承关系反而会将每个Binding
捆绑,抽象方法过度实现等问题。而采用with
可以隔离每个Binding
又能互相调用而实现整个系统运作。