【flutter】WidgetsFlutterBinding是怎样使用mixin的

在这里插入图片描述
最近在看一篇文章的时候,有一段是这么描述的,咋感觉跟我理解的不太一样呢?为了看源码时少走一些弯路,我们就来看看WidgetsFlutterBinding是怎样使用mixin的。

那么, WidgetsFlutterBinding又是什么呢?WidgetsFlutterBinding是绑定widget 框架和Flutter 引擎的桥梁

void runApp(Widget app) {
  final WidgetsBinding binding = WidgetsFlutterBinding.ensureInitialized();
  assert(binding.debugCheckZone('runApp'));
  binding
    ..scheduleAttachRootWidget(binding.wrapWithDefaultView(app))
    ..scheduleWarmUpFrame();
}

我们可以看到,当flutter app启动的第一行代码就是初始化WidgetsFlutterBinding。
WidgetsFlutterBinding 继承了BindingBase,同时通过with扩展了很多binding,这些都是flutter的重要组成部分

GestureBinding 手势系统的binding,响应系统手势事件
SchedulerBinding 我们常说的帧,提供帧开始(onBeginFrame) ,绘制(onDrawFrame)的的时候的回调,监听刷新事件
ServicesBinding 监听平台消息,并发送到defaultBinaryMessenger,简单说就是主要处理原生和Flutter通信
PaintingBinding 绑定绘制库,用于处理图片缓存
SemanticsBinding 语义层和flutter 引擎的桥梁
RendererBinding 处理渲染树

class WidgetsFlutterBinding extends BindingBase with GestureBinding, SchedulerBinding, ServicesBinding, PaintingBinding, SemanticsBinding, RendererBinding, WidgetsBinding {
  static WidgetsBinding ensureInitialized() {
    if (WidgetsBinding._instance == null) {
      WidgetsFlutterBinding();
    }
    return WidgetsBinding.instance;
  }
}

可在WidgetsFlutterBinding.ensureInitialized()中,只是创建了WidgetsFlutterBinding()对象。那么这些binding是怎样完成初始化的呢?它们的执行顺序又是怎样的呢?

首先我们去flutter开发文档简单了解一下mixin,然后在《Flutter实战·第二版》这本书里有这么一句话:
在这里插入图片描述
如果多个mixin 中有同名方法,with 时,会默认使用最后面的 mixin 的,mixin 方法中可以通过 super 关键字调用之前 mixin 或类中的方法。

再回到WidgetsFlutterBinding代码,分析它们的执行顺序:

    
=>WidgetsFlutterBinding()		//WidgetsFlutterBinding 继承自 BindingBase,执行BindingBase()
=>BindingBase()					 //BindingBase()中调用initInstances();
=>initInstances();				 //被子类重写,多个binding中都有该方法的实现,执行最后with的mixin
=>WidgetsBinding.initInstances()  //WidgetsBinding中的initInstances()被执行
=> super.initInstances(); 		 //WidgetsBinding.initInstances()中第一行调用了super,则优先执行super
=>RendererBinding.initInstances();  //RendererBinding倒数第二个被with
...
依此类推

最终初始化顺序:
GestureBinding=>SchedulerBinding=>ServicesBinding=>PaintingBinding=>SemanticsBinding=>RendererBinding=>WidgetsBinding

现在我们已经知道,在WidgetsFlutterBinding这个主类中调用同名方法会遵循以上规则,那么我在其中一个mixin中调用了同名方法,又会怎样去执行呢?在我们查看手势源码GestureBinding的时候,就会遇到这个问题。

//GestureBinding中处理事件
  void _handlePointerEventImmediately(PointerEvent event) {
    HitTestResult? hitTestResult;
    if (event is PointerDownEvent || event is PointerSignalEvent || event is PointerHoverEvent || event is PointerPanZoomStartEvent) {
      assert(!_hitTests.containsKey(event.pointer), 'Pointer of ${event.toString(minLevel: DiagnosticLevel.debug)} unexpectedly has a HitTestResult associated with it.');
      hitTestResult = HitTestResult();
      hitTest(hitTestResult, event.position); ///调用hitTest方法
    } 
    //省略...
  }



//GestureBinding中的hitTest
  @override // from HitTestable
  void hitTest(HitTestResult result, Offset position) {
    result.add(HitTestEntry(this));
  }


//RendererBinding中的hitTest
  @override
  void hitTest(HitTestResult result, Offset position) {
    renderView.hitTest(result, position: position);
    super.hitTest(result, position);
  }

很多人在看到上方源码的时候,自然而然的就会想到执行的是GestureBinding中的hitTest,就不知道怎么往下看了。
而实际上,在mixin中调用同名方法,也会遵循主类的执行规则
主类WidgetsFlutterBinding 扩展的所有binding中,只有GestureBinding和RendererBinding实现了hitTest方法,而RendererBinding后with。因此,在GestureBinding中调用hitTest方法后,会先执行RendererBinding中的hitTest,RendererBinding.hitTest()中会调用 super.hitTest,才会执行到GestureBinding中的hitTest。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值