likes
comments
collection
share

Flutter源码学习pt.1-4总结, WidgetsFlutterBinding的秘密

作者站长头像
站长
· 阅读数 35

跨平台的秘密之一Binding

我们惊讶于Flutter的跨平台特性,一切皆Widget,这些概念对Android开发者来说,都是新奇的,不易接受的,Android的四大组件,是非常经典设计模式,但在UI构建层面,xml+code, 以及 ViewPointer 的耦合,确实相当落后的命令式的写法。真正理解这个UI层面的差异,以及跨平台的的方案,我们最好是通过源码来看高层的设计,如何做到组合式的UI以及一切皆Widget的原理。

Binding 在其中是非常重要的存在. 我们通过一段必须使用的代码了解他。

void main() async {  
    WidgetsFlutterBinding.ensureInitialized();
    runApp();
}

这是我们启动展示我们自己Widget之前,必须调用的,它做了运行我们自己Widget之前的环境准备工作。我们很少会主动看这个写法,因为他像Android开发中的Application, 环境的准备过程经常会被忽略。我们细看一下环境的准备工作,上代码。

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

我们看到WidgetsFlutterBinding 实现了BindingBase并聚合了GestureBinding(点击), SchedulerBinding(帧), ServicesBinding(平台服务), PaintingBinding(图像绘制), SemanticsBinding(语义), RendererBinding(渲染), WidgetsBinding(UI),方法虽然返回WidgetsBinding.instance, 但 初始化的工作,却是WidgetsFlutterBinding, 也就是父类BindingBase的构造函数,上主流程代码。

 BindingBase() {
    if (!kReleaseMode) {
      FlutterTimeline.startSync('Framework initialization');
    }
    
    // 初始化所有Binding
    initInstances();
    // 初始化所有系统级服务
    initServiceExtensions();

    if (!kReleaseMode) {
      FlutterTimeline.finishSync();
    }
  }
  /// GestureBinding
  @override
  void initInstances() {
    super.initInstances();
    _instance = this;
    platformDispatcher.onPointerDataPacket = _handlePointerDataPacket;
  }
  static GestureBinding get instance => BindingBase.checkInstance(_instance);
  static GestureBinding? _instance;

上述流程清晰的展示了,Binding是单例的,当我们调用完成WidgetsFlutterBinding, 所有的系统组件都已完成初始化。我对mixin GestureBinding on BindingBase非常感兴趣,我们之后再探究他的实现原理和用法。我们回头看前面几节分析的SchedulerBinding初始化engine(引擎)如何连接。

mixin SchedulerBinding on BindingBase {
  @override
  void initInstances() {
    super.initInstances();
    _instance = this;

    if (!kReleaseMode) {
      addTimingsCallback((List<FrameTiming> timings) {
        timings.forEach(_profileFramePostEvent);
      });
    }
  }
 }

我们会惊讶的发现SchedulerBinding初始化时并不和系统有任何交互,它像是一个中间层,负责调度,并不关心和系统的交互。但GestureBinding 初始化时,粘合了平台系统PointerFlutter。 这也展示了粘合的另一个作用,和平台粘合。

mixin GestureBinding on BindingBase implements HitTestable, HitTestDispatcher, HitTestTarget {
  @override
  void initInstances() {
    super.initInstances();
    _instance = this;
    platformDispatcher.onPointerDataPacket = _handlePointerDataPacket;
  }
}

总结

Binding有很多, 当前不一一介绍,当使用到的时候,我们再进行分析。概况的来说,Binding是系统和Flutter,Flutter不同功能之间的粘合剂,聚合了运行环境,是运行我们自己Widget的基础。下一篇,预计分析绘制流程以及调试过程

转载自:https://juejin.cn/post/7348646483384320050
评论
请登录