【Flutter】WidgetsFlutterBinding和它的Bindings

我正在参加「掘金·启航计划

runApp入口

Fluttermain函数创建根组件作为入参初始化了WidgetsFlutterBinding

WidgetsFlutterBinding

WidgetsFlutterBinding是一个特殊类继承了BindingBase又混入了各种Binding。而混入with也是Dart比较特殊的语法糖同时也是WidgetsFlutterBinding类特别之处。

WidgetsFlutterBinding实现比较简单只做了初始化功能,实例化单例对象WidgetsBinding。(暂且先不关心它)先分别介绍一下每个Binding的职责。

WidgetsBinding

initInstances初始化函数大致可知WidgetsBinding主要职责是负责脏节点刷新以及平台的本地化、特性变化和帧刷新等监听工作,脏节点组件更新由BuildOwner负责完成。

RendererBinding

initInstances初始化函数中创建了PipelineOwnerRenderView,其主要职责是负责FlutterUI渲染工作,PipelineOwner并是负责渲染的重要类。
图片[1]-【Flutter】WidgetsFlutterBinding和它的Bindings-五八三
此外RenderingFlutterBinding类是类似WidgetsFlutterBinding带有初始化方法ensureInitialized实例化对象。

SemanticsBinding

SemanticsBinding主要处理平台上辅助服务事件,所负责职责比较少。

PaintingBinding

PaintingBinding主要职责管理图片缓存和着色器预热,分别由ImageCacheShaderWarmUp管理。

ServicesBinding

ServicesBinding主要职责创建二进制通信服务、平台软键盘功能、平台系统消息通信和生命周期以及平台插件方法等注册。

  1. SystemChannels.lifecycle.setMessageHandler(_handleLifecycleMessage)负责生命周期
  2. SystemChannels.system.setMessageHandler((dynamic message) => handleSystemMessage(message as Object))负责系统信息监听(例如低内存警告memoryPressure)
  3. _initKeyboard()负责软硬键盘输入信息
  4. SystemChannels.platform.setMethodCallHandler(_handlePlatformMessage)负责平台方法调用

SchedulerBinding

SchedulerBinding负责任务调度处理各种类型任务调度时机,之前讲到的三辆马车运作就是在该类中实现的。其主要能力是和平台帧交互,调度平台帧等待平台的开始帧和绘制帧来驱动三辆马车运作起来从而达到刷新UI和驱动任务的作用。

  1. _timingsCallbacks用于检测GPU耗时检测
  2. handleAppLifecycleStateChanged控制帧状态是否可用(后台情况下不刷新)
  3. _persistentCallbacks_postFrameCallbacks以及_transientCallbacks三个回调分别代表瞬时回调、帧结束回调和动画回调。

GestureBinding

GestureBinding负责手势操作处理对Flutter事件分发管理。

  1. _handlePointerDataPacket接受平台发起事件数据包
  2. _pendingPointerEvents是事件数据包队列
  3. _flushPointerEventQueue循环_pendingPointerEvents队列,只要队列不为空并做处理
  4. handlePointerEvent会通过_handlePointerEventImmediately处理指针事件PointerEvent得到HitTestResult结果
  5. 通过dispatchEventHitTestResult结果分发。

PS:事件分发也是Flutter开发中重要一环,后续可以单独展开说说

mixin & with & on

WidgetsFlutterBinding类实现上可看到with各种xxxBinding,此外其他Bindingmixin且又on其他Binding,这就是dart特殊语法糖:混入类。

  1. Mixin 是一种在多个类层次结构中重用类代码的方法。
  2. Mixin支持混入多个对象。
  3. Mixin 修饰对象不能有构造函数,因此无法直接实例化对象。(除非该对象是Class就不能是Mixin)
  4. on关键字主要为了限制Mixin,例如Mixin类型BonA类,若C希望withB就必须继承A类;Mixin类型B是on了Mixin类型A,若C希望withB同样需要Mixin类型A并且A必须在B的前面

如下是mixinonwith使用场景实操来演示最终结果展示。

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并且withAAAAA当执行todo2()时执行AAtodo2()。由于with特性是找到最远混入对象因此执行输出是"<> todo2 AA",若withAA,AAA那么执行方法就变成是AAAtodo2()输出变为"<> 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直接withAAAS是非法的,因为AAASonAAA,且AAAonA

class CC with AAAS{
  void todo() {


    super.todo();

    print("<> todo CC");

  }

}

图片[2]-【Flutter】WidgetsFlutterBinding和它的Bindings-五八三
因此CC需要继承A然后依次withAAAAAAS(顺序不能乱),另外CC也可以不继承A同样采用with也是可以的,位置同样重要必须在AAAAAAS前面。

class CC extends A with AAA,AAAS{
  void todo() {


    super.todo();

    print("<> todo CC");

  }

}

回顾

再看FlutterBinding设计就很好运用了with思路,每个Binding都有各自职责虽然每个职责又无法做到绝对独立,但每个Binding存在着关联系,如果设计采用继承关系反而会将每个Binding捆绑,抽象方法过度实现等问题。而采用with可以隔离每个Binding又能互相调用而实现整个系统运作。

© 版权声明
THE END
喜欢就支持一下吧
点赞0

Warning: mysqli_query(): (HY000/3): Error writing file '/tmp/MYuW4Z4r' (Errcode: 28 - No space left on device) in /www/wwwroot/583.cn/wp-includes/class-wpdb.php on line 2345
admin的头像-五八三
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

图形验证码
取消
昵称代码图片