Flutter相关

Flutter启动流程解析

2019-11-06  本文已影响0人  only_run

使用Flutter开发项目时,只需要调用入口函数main(MyApp()),Flutter项目就运行起来了;之后进行了哪些操作呢?弄清楚这个问题对提高对Flutter中widget,element,renderObject 的理解非常有帮助
Element持有Widget,可能持有RenderObject 例如:RenderObjectWidget及其子类
Widget是Element的配置信息,用来构建Element树,和渲染树
Element的关键方法 mount,updateChild

入口函数

void main() => runApp(MyApp());
//实际调用
void runApp(Widget app) {
  WidgetsFlutterBinding.ensureInitialized()//1
    ..attachRootWidget(app)//2
    ..scheduleWarmUpFrame();//3
}

注释1 返回WidgetsBinding单例对象 代码如下:

//WidgetsFlutterBinding 
class WidgetsFlutterBinding extends BindingBase with GestureBinding, ServicesBinding, SchedulerBinding, PaintingBinding, SemanticsBinding, RendererBinding, WidgetsBinding {

  static WidgetsBinding ensureInitialized() {
    if (WidgetsBinding.instance == null)
      WidgetsFlutterBinding();
    return WidgetsBinding.instance;
  }
}
//BindingBase
//构造方法
BindingBase() {
  ...
    initInstances();
  ...
  }

首先WidgetsFlutterBinding 继承了BindingBase 并混入(dart中混入及其理解这里不做介绍,可自行百度) SchedulerBinding,RendererBinding,WidgetsBinding等这几个类,并分别对其初始化作为静态对象进行持有 例如:

//SchedulerBinding类
  static SchedulerBinding get instance => _instance;
  static SchedulerBinding _instance;
 @override
  void initInstances() {
    super.initInstances();
    _instance = this;
    window.onBeginFrame = _handleBeginFrame;
    window.onDrawFrame = _handleDrawFrame;
    ...
  }

//RendererBinding类
  @override
  void initInstances() {
    super.initInstances();
    _instance = this;
    _pipelineOwner = PipelineOwner(//创建pipellineOwner对象
      onNeedVisualUpdate: ensureVisualUpdate,
      onSemanticsOwnerCreated: _handleSemanticsOwnerCreated,
      onSemanticsOwnerDisposed: _handleSemanticsOwnerDisposed,
    );
    window
      ..onMetricsChanged = handleMetricsChanged
      ..onTextScaleFactorChanged = handleTextScaleFactorChanged
      ..onPlatformBrightnessChanged = handlePlatformBrightnessChanged
      ..onSemanticsEnabledChanged = _handleSemanticsEnabledChanged
      ..onSemanticsAction = _handleSemanticsAction;
    initRenderView();//创建renderView
    _handleSemanticsEnabledChanged();
    assert(renderView != null);
    addPersistentFrameCallback(_handlePersistentFrameCallback);//添加渲染回调监听
    _mouseTracker = _createMouseTracker();
  }

注释2 创建根widget RenderObjectToWidgetAdapter,并创建渲染树

//WidgetsBinding类
void attachRootWidget(Widget rootWidget) {
    _renderViewElement = RenderObjectToWidgetAdapter<RenderBox>(//2-1
      container: renderView,
      debugShortDescription: '[root]',
      child: rootWidget,
    ).attachToRenderTree(buildOwner, renderViewElement);//2-2
  }

注释2-1创建RenderObjectToWidgetAdapter对象
注释2-2 attachToRenderTree(buildOwner, renderViewElement)返回Element对象 代码如下:

//RenderObjectToWidgetAdapter类 继承 RenderObjectWidget
RenderObjectToWidgetElement<T> attachToRenderTree(BuildOwner owner, [ RenderObjectToWidgetElement<T> element ]) {
    if (element == null) {
      owner.lockState(() {//2-2-1
        element = createElement();
        assert(element != null);
        element.assignOwner(owner);
      });
      owner.buildScope(element, () {//2-2-2
        element.mount(null, null);
      });
    } else {
      element._newWidget = this;
      element.markNeedsBuild();
    }
    return element;
  }

注释2-2-1 通过owner对象创建Element,调用assignOwner(owner)方法 element持有owner对象
注释2-2-2 调用如下

void buildScope(Element context, [ VoidCallback callback ]) {
    if (callback == null && _dirtyElements.isEmpty)
      return;
    ...
    try {
      ...
        try {
          callback();
        } finally {
          assert(() {
            context._debugSetAllowIgnoredCallsToMarkNeedsBuild(false);
            assert(_debugCurrentBuildTarget == context);
            _debugCurrentBuildTarget = debugPreviousBuildTarget;
            _debugElementWasRebuilt(context);
            return true;
          }());
        }
      }
      ...
  }

实际调用的是 element.mount(null, null) ;只是把函数作为参数传递给owner.buildScope而已
继续追踪 element的挂载方法mount

//RenderObjectToWidgetElement类
 @override
  void mount(Element parent, dynamic newSlot) {
    assert(parent == null);
    super.mount(parent, newSlot);
    _rebuild();//1
  }
//依次调用父类mount方法
//RootRenderObjectElement类
@override
  void mount(Element parent, dynamic newSlot) {
    // Root elements should never have parents.
    assert(parent == null);
    assert(newSlot == null);
    super.mount(parent, newSlot);
  }
//RenderObjectElement类
@override
  void mount(Element parent, dynamic newSlot) {
    super.mount(parent, newSlot);
    _renderObject = widget.createRenderObject(this);//2
    assert(() { _debugUpdateRenderObjectOwner(); return true; }());
    assert(_slot == newSlot);
    attachRenderObject(newSlot);//3
    _dirty = false;
  }

注释2 element通过持有的widget创建 渲染对象renderObject,恍然大悟的感觉
注释3 更惊喜 attachRenderObject 构建渲染对象关系,即维护渲染树
(备注:注释3的具体实现是获取上层的Element,维护渲染树关系,这里不做深入研究 )
注释1 在element执行挂载(注释2,注释3)后调用 代码如下:

//RenderObjectToWidgetElement类
void _rebuild() {
 
    try {
      _child = updateChild(_child, widget.child, _rootChildSlot);
      assert(_child != null);
    } catch (exception, stack) {
      ...
  }
//Element类
Element updateChild(Element child, Widget newWidget, dynamic newSlot) {
   ...
    if (newWidget == null) {
      if (child != null)
        deactivateChild(child);
      return null;
    }
    if (child != null) {
      ...这一部分代码 虽然很重要,但是当前不研究
    }
    return inflateWidget(newWidget, newSlot);
  }
//Element类
Element inflateWidget(Widget newWidget, dynamic newSlot) {
    assert(newWidget != null);
    ...
    final Element newChild = newWidget.createElement();//1-1
    assert(() { _debugCheckForCycles(newChild); return true; }());
    newChild.mount(this, newSlot);//1-2
    assert(newChild._debugLifecycleState == _ElementLifecycle.active);
    return newChild;
  }

从代码可知调用顺序 _rebuild->updateChild->inflateWidget,注释1-1调用传入的子widget 创建相应的element 眼熟否? 接着执行 注释1-2 Element 类newChild 的mount方法 又开始挂载下一层Element ,
依次类推 构建整个树状的Element层级结构 和RenderObject层级结构(StatefulWidget和StatelessWidget对应的Element没有渲染对象renderObject)

注释3 调用scheduleWarmUpFrame方法

//SchedulerBinding类
void scheduleWarmUpFrame() {
  ...
    // We use timers here to ensure that microtasks flush in between.
    Timer.run(() {
      assert(_warmUpFrame);
      handleBeginFrame(null);//3-1
    });
    Timer.run(() {
      assert(_warmUpFrame);
      handleDrawFrame();//3-2
      ...
      }
   ...
  }

注释3-1 预处理界面更新 注释3-2处理渲染(这里笼统描述,和Flutter的渲染机制有关系) 继续追踪代码

//SchedulerBinding类
void handleDrawFrame() {
    ...
    try {
     ...
      for (FrameCallback callback in _persistentCallbacks)//1
        _invokeFrameCallback(callback, _currentFrameTimeStamp);

      // POST-FRAME CALLBACKS
      _schedulerPhase = SchedulerPhase.postFrameCallbacks;
      final List<FrameCallback> localPostFrameCallbacks =
          List<FrameCallback>.from(_postFrameCallbacks);
      _postFrameCallbacks.clear();
      for (FrameCallback callback in localPostFrameCallbacks)
        _invokeFrameCallback(callback, _currentFrameTimeStamp);
    } finally {
     ...
    }
  }

 void _invokeFrameCallback(FrameCallback callback, Duration timeStamp, [ StackTrace callbackStack ]) {
  ...
    try {
      callback(timeStamp);
    } catch (exception, exceptionStack) {
      ...
    }
 
  }
}
final List<FrameCallback> _persistentCallbacks = <FrameCallback>[];

  /// Adds a persistent frame callback.
  ///
  /// Persistent callbacks are called after transient
  /// (non-persistent) frame callbacks.
  ///
  /// Does *not* request a new frame. Conceptually, persistent frame
  /// callbacks are observers of "begin frame" events. Since they are
  /// executed after the transient frame callbacks they can drive the
  /// rendering pipeline.
  ///
  /// Persistent frame callbacks cannot be unregistered. Once registered, they
  /// are called for every frame for the lifetime of the application.
  void addPersistentFrameCallback(FrameCallback callback) {//2
    _persistentCallbacks.add(callback);
  }

注释1 遍历了_persistentCallbacks容器,是一个List,存放的是FrameCallback 函数类型 ,_invokeFrameCallback方法实际就是执行 这个容器中的callback对象
然后 这个_persistentCallbacks容器中的FrameCallback 对象 是谁放入的呢? 即谁调用了 注释2 的函数 哪里调用的?
还记得本篇文字 开始位置提到的 RendererBinding类,看initInstances方法

//RendererBinding 类
@override
  void initInstances() {
    super.initInstances();
   ...
    addPersistentFrameCallback(_handlePersistentFrameCallback);
    ...
  }

原来在WidgetFlutterBinding初始化的时候 已经调用了addPersistentFrameCallback方法 添加了函数对象 ~小激动!
看下这个函数对象具体执行了什么操作

//RendererBinding类
void _handlePersistentFrameCallback(Duration timeStamp) {
    drawFrame();
  }
 /// Pump the rendering pipeline to generate a frame.
  ///
  /// This method is called by [handleDrawFrame], which itself is called
  /// automatically by the engine when it is time to lay out and paint a frame.
  ///...
@protected
  void drawFrame() {
    assert(renderView != null);
    pipelineOwner.flushLayout();//1
    pipelineOwner.flushCompositingBits();
    pipelineOwner.flushPaint();//2
    renderView.compositeFrame(); // this sends the bits to the GPU //3
    pipelineOwner.flushSemantics(); // this also sends the semantics to the OS.
  }
@override
  void drawFrame() {
   ...
    try {
      if (renderViewElement != null)
        buildOwner.buildScope(renderViewElement);//3
      super.drawFrame();
      buildOwner.finalizeTree();
    } finally {
      assert(() {
        debugBuildingDirtyElements = false;
        return true;
      }());
    }
    ...
  }

实际上 先调用的是WidgetsBinding类drawFrame方法 然后再调用 其混入的RendererBinding类drawFrame方法,调用注释3 buildScope方法,
和 上文中 提到的 创建根widget RenderObjectToWidgetAdapter 调用attachToRenderTree 注释2-2-2 一样,只不过没有传入callback参数
遍历_dirtyElements 调用标记为dirt的element的 rebuild方法,最终调用widget的build,大功告成!
接着计算布局,进行绘制
pipelOwner是RenderBinding中生成并持有的对象,渲染树的owner
注释1 字面意思刷新布局 每个RenderObject及其子类都持有pipelLineOnwer对象
注释2 刷新绘制 注释3 把计算的显示信息发送给gpu进行渲染
这里不做深入研究

上一篇下一篇

猜你喜欢

热点阅读