zoukankan      html  css  js  c++  java
  • 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刷新屏幕
  • 相关阅读:
    Docker部署大型互联网电商平台
    大数据开发你需要知道的十个技术
    详解Linux运维工程师高级篇(大数据安全方向).
    大数据小项目之电视收视率企业项目05
    大数据小项目之电视收视率企业项目04--完全分布式搭建
    大数据小项目之电视收视率企业项目03
    大数据小项目之电视收视率企业项目02
    大数据小项目之电视收视率企业项目01
    本地Navicat连接虚拟机MySQL
    centos7安装MySQL
  • 原文地址:https://www.cnblogs.com/wwoo/p/flutter-framework-qi-dong-dai-ma-yue-du.html
Copyright © 2011-2022 走看看