Flutter Framework启动代码阅读

首先开启启动原生的应用,然后初始化flutter engine,之后在开启4个Task Runners分别是
Platform Task Runner: 跟Flutter Engine的所有交互(接口调用)必须发生在Platform Thread,对应的native的主线程
UI Task Runner Thread(Dart Runner): UI Task Runner被Flutter Engine用于执行Dart root isolate代码
GPU Task Runner: 被用于执行设备GPU的相关调用
FlutterEngine加之后, 开始执行main函数
IO Task Runner: 负责磁盘数据的读取,主要是图片,提前处理减轻GPU的压力
下面主要是UI Task Runner下的启动过程,其他几个TaskRunner大都在FlutterEngine层

Flutter main函数

它首先创建了一个MaterailApp,通常会叫它根视图,其实最终它会作为真正的根视图的第一个child
然后执行WidgetsFlutterBinding,绑定flutterEngine的相关callback事件
构建ElementTree和RenderTree, WidgetTree在我们代码里就能看到了,由开发者调整。它们的先后顺序是 WidgetTree -> ElementTree -> RenderTree
然后通知Flutter Engine预热,刷新当前视图,而不是等待vsync信号

void main() {
  runApp(
    MaterialApp(
      title: 'demo',
      home: HomePage(),
    ),
  );
}
void runApp(Widget app) {
  WidgetsFlutterBinding.ensureInitialized()
    ..scheduleAttachRootWidget(app)
    ..scheduleWarmUpFrame();
}

1. 创建根RootWidget

1.1 这里一般定义为MaterialApp, 它初始化了很多属性它是一个使用material design的应用

const MaterialApp({
    Key key,
    this.navigatorKey,
    this.home,
    this.routes = const <String, WidgetBuilder>{},
    this.initialRoute,
    this.onGenerateRoute,
    this.onGenerateInitialRoutes,
    this.onUnknownRoute,
    this.navigatorObservers = const <NavigatorObserver>[],
    this.builder,
    this.title = '',
    this.onGenerateTitle,
    this.color,
    this.theme,
    this.darkTheme,
    this.themeMode = ThemeMode.system,
    this.locale, //app的初始化local
    this.localizationsDelegates,//设置app localizations的delegate,用于提供翻译字符串
    this.localeListResolutionCallback,//app的local修改后的回调
    this.localeResolutionCallback,//用于拦截修改当前支持的local
    this.supportedLocales = const <Locale>[Locale('en', 'US')],//指定app支持哪些local,不指定则采用系统的local
    this.debugShowMaterialGrid = false,
    this.showPerformanceOverlay = false,
    this.checkerboardRasterCacheImages = false,
    this.checkerboardOffscreenLayers = false,
    this.showSemanticsDebugger = false,
    this.debugShowCheckedModeBanner = true,
    this.shortcuts,
    this.actions,
  })

1.2 MaterialApp中的信息最终会传递给WdigetsApp, 具体实现在 _WidgetsAppState

  _WidgetsAppState
    @override
  void initState() {
    super.initState();
    //创建GlobalKey,缓存rootnavigator
    _updateNavigator();
    //获取系统的local信息,并回调给materialApp
    _locale = _resolveLocales(WidgetsBinding.instance.window.locales, widget.supportedLocales);
    WidgetsBinding.instance.addObserver(this);
  }
  //创建Router
  Route<dynamic> _onGenerateRoute(RouteSettings settings) 
    ...
    widget.onGenerateRoute(settings);
  //创建unknownRoot
  Route<dynamic> _onUnknownRoute(RouteSettings settings) {

  //监听native的导航事件
  Future<bool> didPopRoute() async //如果为android则为返回按键
  Future<bool> didPushRoute(String route) async

  //系统local处理
  void didChangeLocales(List<Locale> locales) {
    final Locale newLocale = _resolveLocales(locales, widget.supportedLocales);
    //处理local
    Locale _resolveLocales(List<Locale> preferredLocales, Iterable<Locale> supportedLocales) {
    // 过滤local,用于修改local,如果取不到对应的local则采用相近的local
    if (widget.localeListResolutionCallback != null) {
      final Locale locale = widget.localeListResolutionCallback(preferredLocales, widget.supportedLocales);
      //处理MaterialApp local回调信息,优先选择系统的默认local
       if (widget.localeResolutionCallback != null) {
      final Locale locale = widget.localeResolutionCallback(
        preferredLocales != null && preferredLocales.isNotEmpty ? preferredLocales.first : null,
        widget.supportedLocales,
      );

1.3 根视图执行build方法, 构建Element的配置信息

  • 可以看到根视图最终的Child的是一个 Navigator , 而 Navigator 会挂在一个 可视化的rootWidget , 通过initialRoute去查找。
Widget build(BuildContext context) {
    Widget navigator;
    if (_navigator != null) {
      navigator = Navigator(
        key: _navigator,
        //优先选择native的routeName
        initialRoute: WidgetsBinding.instance.window.defaultRouteName != Navigator.defaultRouteName
            ? WidgetsBinding.instance.window.defaultRouteName
            : widget.initialRoute ?? WidgetsBinding.instance.window.defaultRouteName,
        //设置route的构造方法
        onGenerateRoute: _onGenerateRoute,
        //设置initialRoute
        onGenerateInitialRoutes: widget.onGenerateInitialRoutes == null
          ? Navigator.defaultGenerateInitialRoutes
          : (NavigatorState navigator, String initialRouteName) {
            return widget.onGenerateInitialRoutes(initialRouteName);
          },
        //设置位置的root
        onUnknownRoute: _onUnknownRoute,
        //设置navigator的观察者
        observers: widget.navigatorObservers,
      );
    }

    Widget result;
    if (widget.builder != null) {
      result = Builder(
        builder: (BuildContext context) {
          return widget.builder(context, navigator);
        },
      );
    } else {
      assert(navigator != null);
      result = navigator;
    }
    //设置样式,DefaultTextStyle继承于InheritedTheme
    if (widget.textStyle != null) {
      result = DefaultTextStyle(
        style: widget.textStyle,
        child: result,
      );
    }
    ...
    Widget title;
    if (widget.onGenerateTitle != null) {
      //转换child的context作用域,避免loaclizations widget构建失败
      title = Builder(
        builder: (BuildContext context) {
          final String title = widget.onGenerateTitle(context);
          assert(title != null, 'onGenerateTitle must return a non-null String');
          return Title(
            title: title,
            color: widget.color,
            child: result,
          );
        },
      );
    } else {
      title = Title(
        title: widget.title,
        color: widget.color,
        child: result,
      );
    }

    final Locale appLocale = widget.locale != null
      ? _resolveLocales(<Locale>[widget.locale], widget.supportedLocales)
      : _locale;
    ...
    //捕捉用户意图
    return Shortcuts(
      shortcuts: widget.shortcuts ?? WidgetsApp.defaultShortcuts,
      debugLabel: '<Default WidgetsApp Shortcuts>',
      child: Actions(
        actions: widget.actions ?? WidgetsApp.defaultActions,
        child: FocusTraversalGroup(
          policy: ReadingOrderTraversalPolicy(),
          //获取native屏幕大小,绑定dart.ui window回调信息(textScale/brightness)
          child: _MediaQueryFromWindow(
              //通过引入_LocalizationsScope包装根视图 `Title` ,同时提供了local data给它的所有子widget
            child: Localizations(
              locale: appLocale,
              delegates: _localizationsDelegates.toList(),
              child: title,
            ),
          ),
        ),
      ),
    );
  }

2. 绑定FlutterEngine相关服务扩展

  • 执行WidgetsFlutterBinding.ensureInitialized方法初始化, 在初始化方法中完成flutterEngine所有方法的绑定
  • 创建全局单例类 WidgetsFlutterBinding , 对应代码如下
//WidgetsFlutterBinding初始化对象 `this` 赋值给了 `WidgetsBinding.instance` ,通过类属性 `instance` 让它成为了全局单例子
      WidgetsFlutterBinding();
    return WidgetsBinding.instance;
  • WidgetsFlutterBinding关系图如下,通过mixin实现多重继承完成了FlutterEngine相关的事件绑定,它的绑定事件按照如下with从左到右的顺序一次绑定,由此可见 WidgetsBindings 依赖的 FlutterEngine`服务最多, 因此它需要最后再绑定.
class WidgetsFlutterBinding extends BindingBase with GestureBinding, ServicesBinding, SchedulerBinding, PaintingBinding, SemanticsBinding, RendererBinding, WidgetsBinding {

2.1 BindingBase:

提供最基本的服务订阅, 提供初始化 WidgetsBinding.instance 的方法

abstract class BindingBase {
 
  BindingBase() {
 //开启一个同步执行的Timeline,初始化flutterWidgets运行所必须的的订阅事件
 //作为一个base class为子类提供断言
    developer.Timeline.startSync('Framework initialization');
    ...
    //初始化mixin相关的实例对象
    initInstances();
    ...
    //提供便利方法,执行 flutter engine提供的 `ext.flutter.$name` 方法
    initServiceExtensions();
    ...
    //通知native,widgets初始化完毕,可以开始绘制
    developer.postEvent('Flutter.FrameworkInitialization', <String, String>{});
    //解除Timeline的同步限制
    developer.Timeline.finishSync();
  }

  //flutter engine提供的窗口,用于绑定native的service,监听flutter engine的回调事件
  ui.Window get window => ui.window;
  
  //定义一个抽象的方法,供mixin类初始化实例对象
  @protected
  @mustCallSuper
  void initInstances() {
    assert(() {
      _debugInitialized = true;
      return true;
    }());
  }
  
  //注册flutter engine的扩展信息
  @protected
  @mustCallSuper
  void initServiceExtensions() {
    assert(!_debugServiceExtensionsRegistered);

    assert(() {
      //注册dart vm的 hot reload事件,用于debug时快速更新app
      registerSignalServiceExtension(
        name: 'reassemble',
        callback: reassembleApplication,
      );
      return true;
    }());

    if (!kReleaseMode && !kIsWeb) {
        //注册dart vm的退出事件
      registerSignalServiceExtension(
        name: 'exit',
        callback: _exitApplication,
      );
      registerServiceExtension(
        name: 'saveCompilationTrace',
        callback: (Map<String, String> parameters) async {
          return <String, dynamic>{
            'value': ui.saveCompilationTrace(),
          };
        },
      );
    }

    assert(() {
      const String platformOverrideExtensionName = 'platformOverride';
      //注册platformOverride的回调事件
      registerServiceExtension(
        name: platformOverrideExtensionName,
        callback: (Map<String, String> parameters) async {
          if (parameters.containsKey('value')) {
            switch (parameters['value']) {
              case 'android':
                debugDefaultTargetPlatformOverride = TargetPlatform.android;
                break;
              case 'fuchsia':
                debugDefaultTargetPlatformOverride = TargetPlatform.fuchsia;
                break;
              case 'iOS':
                debugDefaultTargetPlatformOverride = TargetPlatform.iOS;
                break;
              case 'linux':
                debugDefaultTargetPlatformOverride = TargetPlatform.linux;
                break;
              case 'macOS':
                debugDefaultTargetPlatformOverride = TargetPlatform.macOS;
                break;
              case 'windows':
                debugDefaultTargetPlatformOverride = TargetPlatform.windows;
                break;
              case 'default':
              default:
                debugDefaultTargetPlatformOverride = null;
            }
            _postExtensionStateChangedEvent(
              platformOverrideExtensionName,
              defaultTargetPlatform.toString().substring('$TargetPlatform.'.length),
            );
            await reassembleApplication();
          }
          return <String, dynamic>{
            'value': defaultTargetPlatform
                     .toString()
                     .substring('$TargetPlatform.'.length),
          };
        },
      );
      return true;
    }());
    assert(() {
      _debugServiceExtensionsRegistered = true;
      return true;
    }()); 
  }

  //定义Timeline的同步执行事件,通过lock数量控制是否将解除timeline的同步执行
  //对关键操作提供同步执行操作 
  @protected
  Future<void> lockEvents(Future<void> callback()) {
    developer.Timeline.startSync('Lock events');
//调用shell的退出命令,关闭程序
Future<void> _exitApplication() async {
  exit(0);
}

2.2 GestureBinding

  • 注册手势的点击事件回调
mixin GestureBinding on BindingBase implements HitTestable, HitTestDispatcher, HitTestTarget {
  @override
  void initInstances() {
    super.initInstances();
    _instance = this;
    window.onPointerDataPacket = _handlePointerDataPacket;
  }
  • 注册MethodChannel的回调

lifeCycle的监听, frame刷新

mixin ServicesBinding on BindingBase {
  @override
  void initInstances() {
    super.initInstances();
    _instance = this;
    _defaultBinaryMessenger = createBinaryMessenger();
    window.onPlatformMessage = defaultBinaryMessenger.handlePlatformMessage;
    initLicenses();
    SystemChannels.system.setMessageHandler(handleSystemMessage);
  }

2.3 PaintingBinding

  • 绑定绘制事件
mixin PaintingBinding on BindingBase, ServicesBinding {
  @override
  void initInstances() {
    super.initInstances();
    _instance = this;
    _imageCache = createImageCache();
    if (shaderWarmUp != null) {
      shaderWarmUp.execute();
    }
  }

2.4 RendererBinding

  • 绑定Render事件, 初始化根视图的 RenderObject , 它比较特殊, 不同于一般的RenderObject, 因为需要提供窗口的大小, 所以系统对它进行了一次包装, 根据源码, 窗口的大小和deviceRatio就是在这个时候设置的
class RenderView extends RenderObject with RenderObjectWithChildMixin<RenderBox> {
  RenderView({
    RenderBox child,
    @required ViewConfiguration configuration,
    @required ui.Window window,
  })

mixin RendererBinding on BindingBase, ServicesBinding, SchedulerBinding, GestureBinding, SemanticsBinding, HitTestable {
  @override
  void initInstances() {
    super.initInstances();
    _instance = this;
    //初始化渲染管道owner,绑定flutter engine的绘制视图的回调事件
    _pipelineOwner = PipelineOwner(
      onNeedVisualUpdate: ensureVisualUpdate,
      onSemanticsOwnerCreated: _handleSemanticsOwnerCreated,
      onSemanticsOwnerDisposed: _handleSemanticsOwnerDisposed,
    );
    //绑定flutter engine的 文本大小,测量信息,屏幕亮度,语义行为事件
    window
      ..onMetricsChanged = handleMetricsChanged
      ..onTextScaleFactorChanged = handleTextScaleFactorChanged
      ..onPlatformBrightnessChanged = handlePlatformBrightnessChanged
      ..onSemanticsEnabledChanged = _handleSemanticsEnabledChanged
      ..onSemanticsAction = _handleSemanticsAction;
      //初始化renderRootObject
    initRenderView();
    _handleSemanticsEnabledChanged();
    assert(renderView != null);
    //监听系统的framecallback事件执行 `drawFrame`
    addPersistentFrameCallback(_handlePersistentFrameCallback);
    initMouseTracker();
  }

WidgetsBindings

  • 注册flutter engine widget相关的事件
mixin WidgetsBinding on BindingBase, ServicesBinding, SchedulerBinding, GestureBinding, RendererBinding, SemanticsBinding {
  @override
  void initInstances() {
    super.initInstances();
    _instance = this;
    ...
    _buildOwner = BuildOwner();
    buildOwner.onBuildScheduled = _handleBuildScheduled;
    window.onLocaleChanged = handleLocaleChanged;
    window.onAccessibilityFeaturesChanged = handleAccessibilityFeaturesChanged;
    SystemChannels.navigation.setMethodCallHandler(_handleNavigationInvocation);
    FlutterErrorDetails.propertiesTransformers.add(transformDebugCreator);

3. 装配RootWidget

  • FlutterEngine 相关的Service绑定以后, 开始执行 scheduleAttachRootWidget , 这里通过Scheduler一个时间间隔为0的task来执行RootWidget绑定, Timer内部包装了一个_RootZone的环境,
//在初始化的时候根据deviceRatio和屏幕大小初始化Root renderObject,赋值给`PiplineOwner`
mixin RendererBinding on BindingBase, ServicesBinding, SchedulerBinding, GestureBinding, SemanticsBinding, HitTestable {
  set renderView(RenderView value) {
    assert(value != null);
    _pipelineOwner.rootNode = value;
  }
  void initRenderView() {
    assert(renderView == null);
    renderView = RenderView(configuration: createViewConfiguration(), window: window);
    renderView.prepareInitialFrame();
  }
  ...

mixin WidgetsBinding on BindingBase, ServicesBinding, SchedulerBinding, GestureBinding, RendererBinding, SemanticsBinding {
  void scheduleAttachRootWidget(Widget rootWidget) {
    Timer.run(() {
      attachRootWidget(rootWidget);
    });
  }
   
    void attachRootWidget(Widget rootWidget) {
    _readyToProduceFrames = true;
    //根据RootRenderObject和RootWidget创建真正的RootWidget
    _renderViewElement = RenderObjectToWidgetAdapter<RenderBox>(
      container: renderView, //此处renderView是RenderBinding在初始化的时候根据窗口大小还有设备像素比创建,并赋值给`_pipelineOwner`
      debugShortDescription: '[root]',
      child: rootWidget, //runApp传入的rootWidget
    ).attachToRenderTree(buildOwner, renderViewElement as RenderObjectToWidgetElement<RenderBox>);
  } // buildOwner是在WidgetBindings创建,用于管理ElementTree更新

    RenderObjectToWidgetElement<T> attachToRenderTree(BuildOwner owner, [ RenderObjectToWidgetElement<T> element ]) {
    if (element == null) {
      owner.lockState(() {
        element = createElement();//创建RootElment
        assert(element != null);
        element.assignOwner(owner);
      });
      owner.buildScope(element, () {
        element.mount(null, null);
      });
      // This is most likely the first time the framework is ready to produce
      // a frame. Ensure that we are asked for one.
      SchedulerBinding.instance.ensureVisualUpdate();
    } else {
      element._newWidget = this;
      element.markNeedsBuild();
    }
    return element;
  }
//每当element装配到ElementTree中时创建RenderObject
abstract class RenderObjectElement extends Element {
    @override
  void mount(Element parent, dynamic newSlot) {
    super.mount(parent, newSlot);
    assert(() {
      _debugDoingBuild = true;
      return true;
    }());
    _renderObject = widget.createRenderObject(this);
    ...
    //然后将renderObject插入到它的先组上面,如此循环,最终形成了ElementTree和RrenderTree, ElmentTree节点更触发RenderTree节点的更新,Widget作为Element的配置信息,触发Element的更新。
  @override
  void attachRenderObject(dynamic newSlot) {
    assert(_ancestorRenderObjectElement == null);
    _slot = newSlot;
    _ancestorRenderObjectElement = _findAncestorRenderObjectElement();
    _ancestorRenderObjectElement?.insertChildRenderObject(renderObject, newSlot);
    final ParentDataElement<ParentData> parentDataElement = _findAncestorParentDataElement();
    if (parentDataElement != null)
      _updateParentData(parentDataElement.widget);
  }

根据上面的执行顺序可以看出, RootWidget最先创建,然后是RootRenderObject(PiplelineOwner负责管理RenderTree),

4. scheduleWarmUpFrame

  • 向flutter主动请求刷新,而不是被动的通过vsync刷新
mixin SchedulerBinding on BindingBase, ServicesBinding {
  void scheduleWarmUpFrame() {
    if (_warmUpFrame || schedulerPhase != SchedulerPhase.idle)
      return;

    _warmUpFrame = true;
    //用于开启一个同步事件,最终会提交一个event task到flutter engine
    /**
    // timeline.dart
    external void _reportTaskEvent(int taskId, String phase, String category,
    String name, String argumentsAsJson);   
    */
    Timeline.startSync('Warm-up frame');
    final bool hadScheduledFrame = _hasScheduledFrame;
    // We use timers here to ensure that microtasks flush in between.
    Timer.run(() {
      assert(_warmUpFrame);
      handleBeginFrame(null); //通知flutter engine 刷新
    });
    Timer.run(() {
      ...
      handleDrawFrame();
      resetEpoch();
      _warmUpFrame = false;
      if (hadScheduledFrame)
        scheduleFrame(); //  window.scheduleFrame(); ->  void scheduleFrame() native 'Window_scheduleFrame';
    }); 
    lockEvents(() async {
      await endOfFrame;
      Timeline.finishSync();
    });
  }

总结

Flutter App在启动时主要干了以下几件事情:

  1. 开启main isolate,在默认的mainZone内运行了main函数.
  2. 创建MaterialApp(或者是自定义的rootWidget)
  3. 绑定flutter engine相关的服务,系统点击事件,键盘,屏幕,亮度,字体,绘制回调,辅助提示,vsync信息,system.platform channels ...,详细参照启动时Widgetsbinding的几个mixin类的initialServices方法和dart.ui
  4. 构建RenderTree和ElementTree
  5. 主动通知flutter engine刷新屏幕
原文地址:https://www.cnblogs.com/wwoo/p/flutter-framework-qi-dong-dai-ma-yue-du.html