Flutter启动runApp与三棵树诞生流程

背景

Flutter的第一行程序开始, Dart的main方法中通过调用runApp方法把开发者自己编写的Widget传递进去, 编译运行后, 得到开发者预期的效果。我们很好奇, 这背后经历了什么?或者说, 你经常听到的Flutter三棵树核心机制是什么?接下来, 我们一起探讨。

Flutter程序入口

开发者自己编写的Flutter App一般入口都是在main方法, 其内部通过调用runApp方法将我们整个应用的Widget添加并运行。runApp的方法实现如下:

void runApp(Widget app) {
  WidgetsFlutterBinding.ensureInitialized()
    ..scheduleAttachRootWidget(app)
    ..scheduleWarmUpFrame();
}
复制代码

上面三行代码代表Flutter启动的核心三步(级联运算符调用)

  • WidgetsFlutterBinding初始化(ensureInitialized)
  • 调度、绑定根节点, 创建核心三棵树(scheduleAttachRootWidget(app))
  • 调度、绘制热身帧(scheduleWarmUpFrame())

WidgetsFlutterBinding实例及初始化

源码如下:


This is the glue that binds the framework to the Flutter engine.

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

分析源码, 可以发现。这个类上面的一行代码: This is the glue that binds the framework to the Flutter engine. 意思是WidgetsFlutterBinding类是Widget框架和Flutter engine的桥梁。 也是整个Flutter的应用层核心。WidgetsFlutterBinding继承自BindingBase, 并且with了大量的mixin类。通过 ensureInitialized() 方法我们可以得到一个全局单例的 WidgetsFlutterBinding 实例,且 mixin 的一堆 XxxBinding 也被实例化。

BindingBase 抽象类的构造方法中会调用initInstances()方法,而各种 mixin 的 XxxBinding 实例化重点也都在各自的initInstances()方法中,每个 XxxBinding 的职责不同,如下:

  • WidgetsFlutterBinding: Widget框架和Flutter engine的桥梁核心桥梁主体,Flutter app 全局唯一。

  • BindingBase: 绑定服务抽象类。

  • GestureBinding: 绑定手势事件。处理屏幕事件分发及事件回调处理, 初始化方法中重点是把事件处理回调_handlePointerDataPacket函数赋值给window的属性, 以便window收到屏幕事件后调用, window实例是Framework层与Engine层处理屏幕事件的桥梁。

    void initInstances() {
      super.initInstances();
      _instance = this;
      window.onPointerDataPacket = _handlePointerDataPacket;
    }
    复制代码
  • SchedulerBinding: Flutter绘制调度器相关绑定类, debug编译模式时统计绘制流程时长等操作。

  • ServicesBinding: Flutter系统平台消息监听绑定类。Platform与Flutter层通信相关服务. 同时注册监听了应用的声明周期。

  • PaintingBinding: Flutter绘制预热缓存等绑定类。重要的是, 绑定了图片缓存。

      void initInstances() {
        super.initInstances();
        _instance = this;
        _imageCache = createImageCache();
        shaderWarmUp?.execute();
      }
    复制代码
  • SemanticsBinding: 语义树和Flutter引擎之间的粘合剂绑定类。

  • RendererBinding: 渲染树和Flutter引擎之间的粘合剂绑定类, 重点是持有了渲染树的根节点。RenderView 就是 RenderObject 渲染树的根节点。

    void initRenderView() {
      assert(!_debugIsRenderViewInitialized);
      assert(() {
        _debugIsRenderViewInitialized = true;
        return true;
      }());
      renderView = RenderView(configuration: createViewConfiguration(), window: window);
      renderView.prepareInitialFrame();
    }
    复制代码
  • WidgetsBinding: Widget树和Flutter引擎之间的粘合剂绑定类。

从上面Flutter的runApp启动方法中, 可以看出, 这些XxxBinding承担的角色大致是一个桥梁关联绑定, 如下:

因为我们主要探讨Flutter启动主流程机制, 以及三棵树的诞生流程, 所以我们需要重点关注RendererBinding 和 WidgetsBinding 类的initInstances()方法, 如下:

## RendererBinding类

/// The glue between the render tree and the Flutter engine.

渲染树(render tree) 和 Flutter engine之间的桥梁

mixin RendererBinding on BindingBase, ServicesBinding, SchedulerBinding, GestureBinding, SemanticsBinding, HitTestable {
  @override
  void initInstances() {
    super.initInstances();
    _instance = this;
    /*
    创建管理rendering渲染管道的类, 提供接口调用来触发渲染
    */
    _pipelineOwner = PipelineOwner(
      onNeedVisualUpdate: ensureVisualUpdate,
      onSemanticsOwnerCreated: _handleSemanticsOwnerCreated,
      onSemanticsOwnerDisposed: _handleSemanticsOwnerDisposed,
    );
    
    /*
    window变化相关的回调监听
    */
    window
      ..onMetricsChanged = handleMetricsChanged
      ..onTextScaleFactorChanged = handleTextScaleFactorChanged
      ..onPlatformBrightnessChanged = handlePlatformBrightnessChanged
      ..onSemanticsEnabledChanged = _handleSemanticsEnabledChanged
      ..onSemanticsAction = _handleSemanticsAction;
      
    /*
    创建RenderView对象, 也就是RenderObject渲染树的根节点
    */
    initRenderView();
    
    ......
  }
  

/// Creates a [RenderView] object to be the root of the
/// [RenderObject] rendering tree, and initializes it so that it
/// will be rendered when the next frame is requested.
///
/// Called automatically when the binding is created.

创建渲染树的根节点对象

void initRenderView() {
  
 ......
 
  /*
  创建渲染树的根节点对象
  */
  renderView = RenderView(configuration: createViewConfiguration(), window: window);
  renderView.prepareInitialFrame();
}
 
/*
 定义renderView的get方法,获取自_pipelineOwner.rootNode
*/
RenderView get renderView => _pipelineOwner.rootNode! as RenderView;
 
/*
定义renderView的set方法,上面initRenderView()中实例化赋值就等于给_pipelineOwner.rootNode也进行了赋值操作。
*/

set renderView(RenderView value) {
   assert(value != null);
   _pipelineOwner.rootNode = value;
}


## WidgetsBinding类

/// The glue between the widgets layer and the Flutter engine.

widgets 和 Flutter engine之间的桥梁

mixin WidgetsBinding on BindingBase, ServicesBinding, SchedulerBinding, GestureBinding, RendererBinding, SemanticsBinding {
  @override
  void initInstances() {
    super.initInstances();
    _instance = this;

    assert(() {
      _debugAddStackFilters();
      return true;
    }());

    /*
    创建一个管理Widgets的类对象
    BuildOwner类用来跟踪哪些Widget需要重建,并处理用于Widget树的其他任务,例如管理不活跃的Widget等,调试模式触发重建等。
    */
    _buildOwner = BuildOwner();
    
    /*
    回调方法赋值,当第一个可构建元素被标记为脏时调用。
    */
    buildOwner!.onBuildScheduled = _handleBuildScheduled;
    
    /*
    回调方法赋值,当本地配置变化或者AccessibilityFeatures变化时调用。
    */
    window.onLocaleChanged = handleLocaleChanged;
    window.onAccessibilityFeaturesChanged = handleAccessibilityFeaturesChanged;
    SystemChannels.navigation.setMethodCallHandler(_handleNavigationInvocation);
    
    ......
  }


复制代码

分析上面的初始化过程, 以及重点关注的RendererBinding、WidgetsBinding初始化方法。我们可以知道RendererBinding 中的 RenderView 就是 RenderObject 渲染树的根节点。我们可以得到以下流程图:

runApp加载流程.png

runApp加载流程.png

Guess you like

Origin juejin.im/post/7031456901216862238