flutter setState解析 & frameWork层和engine层的交互

有状态的widget(StatefulWidget) UI刷新要调用setState. setState做了什么实现的页面刷新呢, 刷新流程是怎样的呢?

上代码

@protected
  void setState(VoidCallback fn) {
    ...    
    _element.markNeedsBuild(); 
  }
void markNeedsBuild() {
    ...
    if (dirty)
      return;
    _dirty = true;
    owner.scheduleBuildFor(this); ///关键代码
  }

插播提问: owner是谁?

  • BuildOwner _owner;
@mustCallSuper
  void mount(Element parent, dynamic newSlot) {
    ...
    _parent = parent;
    if (parent != null) 
      _owner = parent.owner; 
    ...
  }

看源码可知, 子 element 和父 element 公用一个 _owner.
所以, 要确定 _owner 是谁, 先要确定 root element 是谁?

看源码注释我们发现一个抽象类: RootRenderObjectElement

/// The element at the root of the tree.
///
/// Only root elements may have their owner set explicitly. All other
/// elements inherit their owner from their parent.
abstract class RootRenderObjectElement extends RenderObjectElement

接着找到继承了RenderObjectToWidgetElement的类: RootRenderObjectElement, 至此我们就找到了root element的类名

/// A [RootRenderObjectElement] that is hosted by a [RenderObject].
///
/// This element class is the instantiation of a [RenderObjectToWidgetAdapter]
/// widget. It can be used only as the root of an [Element] tree (it cannot be
/// mounted into another [Element]; it's parent must be null).
///
/// In typical usage, it will be instantiated for a [RenderObjectToWidgetAdapter]
/// whose container is the [RenderView] that connects to the Flutter engine. In
/// this usage, it is normally instantiated by the bootstrapping logic in the
/// [WidgetsFlutterBinding] singleton created by [runApp].
class RenderObjectToWidgetElement<T extends RenderObject> extends RootRenderObjectElement

1.1 确定root element及owner

renderViewElement就是root element.
buildOwner就是我们要找的owner, 他在WidgetsBinding.initInstances方法内初始化的

mixin WidgetsBinding on BindingBase, ServicesBinding, SchedulerBinding, GestureBinding, RendererBinding, SemanticsBinding {
  void attachRootWidget(Widget rootWidget) {
    _readyToProduceFrames = true;
    _renderViewElement = RenderObjectToWidgetAdapter<RenderBox>(
      container: renderView,
      debugShortDescription: '[root]',
      child: rootWidget,
    ).attachToRenderTree(buildOwner, renderViewElement as RenderObjectToWidgetElement<RenderBox>);
  }
  
  RenderObjectToWidgetElement<T> attachToRenderTree(BuildOwner owner, [ RenderObjectToWidgetElement<T> element ]) {
  	///空判断
    if (element == null) {
      owner.lockState(() {
        element = createElement();
        assert(element != null);
        ///给element赋值owner
        element.assignOwner(owner);
      });
      ///rebuild
      owner.buildScope(element, () {
      	///因为是root element, 所以super为null
        element.mount(null, null);
      });
      ///首次VSYNC注册流程
      SchedulerBinding.instance.ensureVisualUpdate();
    } 
	///不为空: markNeedsBuild, 标记为脏,
	else {
      element._newWidget = this;
      element.markNeedsBuild();
    }
    return element;
  }
  void assignOwner(BuildOwner owner) {
    _owner = owner;
  }
  

1.2 owner初始化

mixin WidgetsBinding on BindingBase, ServicesBinding, SchedulerBinding, GestureBinding, RendererBinding, SemanticsBinding {
  @override
  void initInstances() {
    super.initInstances();
    ...
	///创建 owner
    _buildOwner = BuildOwner(); 
    buildOwner.onBuildScheduled = _handleBuildScheduled; 
    ...
  }
}

确定了owner, 接着往下看.

///BuildOwner
void scheduleBuildFor(Element element) {
    ...
    if (!_scheduledFlushDirtyElements && onBuildScheduled != null) {
      _scheduledFlushDirtyElements = true;
      ///这是一个回调, 在WidgetsBinding.initInstances初始化的
      ///也是注册vsync信号
      onBuildScheduled(); ///参见1.3
    }
    ///添加到脏列表
    _dirtyElements.add(element);
    element._inDirtyList = true;
  }

1.3 vsync 垂直信号注册

在1.2 owner初始化可知: onBuildScheduled回调调用的是 _handleBuildScheduled方法;

  void _handleBuildScheduled() {
    ...
    ensureVisualUpdate();
  }
  void ensureVisualUpdate() {
    switch (schedulerPhase) {
      case SchedulerPhase.idle:
      case SchedulerPhase.postFrameCallbacks:
        scheduleFrame();
        return;
      case SchedulerPhase.transientCallbacks:
      case SchedulerPhase.midFrameMicrotasks:
      case SchedulerPhase.persistentCallbacks:
        return;
    }
  }
  void scheduleFrame() {
    if (_hasScheduledFrame || !framesEnabled)
      return;
    assert(() {
      if (debugPrintScheduleFrameStacks)
        debugPrintStack(label: 'scheduleFrame() called. Current phase is $schedulerPhase.');
      return true;
    }());
    ensureFrameCallbacksRegistered(); ///初始化vsync回调
    window.scheduleFrame(); ///注册vsync信号
    _hasScheduledFrame = true;
  }
  @protected
  void ensureFrameCallbacksRegistered() {
 	///两个关键回调赋值, engine层的vsync信号到来时会回调他俩
    window.onBeginFrame ??= _handleBeginFrame;
    window.onDrawFrame ??= _handleDrawFrame;
  }

  ///window.dart
  ///这里的native关键字类似于java JNI的使用, 去调用engine层对应的C++方法
  ///该方法主要注册了vsync信号, 当vsync信号来到, 回调到framework层, 去刷新标记为dirt的脏element
  void scheduleFrame() native 'PlatformConfiguration_scheduleFrame';

2.1 engine层

接下来是engine层的代码, 贴一个大佬的文章:
Flutter渲染机制—UI线程

engine层的 c++代码就略过了, 感兴趣的小伙伴自行查看代码
engine github地址, 我这里直接贴流程图了

  1. VSYNC注册流程图
    在这里插入图片描述

  2. Engine层处理流程图
    在这里插入图片描述

  3. Framework层处理流程图
    在这里插入图片描述

3.1 vsync信号到来时回调onBeginFrame和onDrawFrame

当vsync信号到来时, engine会调用framework层window类的两个回调
onBeginFrame和onDrawFrame

///window.dart

void _handleBeginFrame(Duration rawTimeStamp) {
    if (_warmUpFrame) {
      assert(!_ignoreNextEngineDrawFrame);
      _ignoreNextEngineDrawFrame = true;
      return;
    }
    handleBeginFrame(rawTimeStamp);
  }

  void _handleDrawFrame() {
    if (_ignoreNextEngineDrawFrame) {
      _ignoreNextEngineDrawFrame = false;
      return;
    }
    handleDrawFrame();
  }
  ///主要看下这个方法
  void handleDrawFrame() {
    assert(_schedulerPhase == SchedulerPhase.midFrameMicrotasks);
    Timeline.finishSync(); // end the "Animate" phase
    try {
      // PERSISTENT FRAME CALLBACKS
      _schedulerPhase = SchedulerPhase.persistentCallbacks;
      ///遍历_persistentCallbacks并调用
      for (final FrameCallback callback in _persistentCallbacks)
        _invokeFrameCallback(callback, _currentFrameTimeStamp!);

      // POST-FRAME CALLBACKS
      _schedulerPhase = SchedulerPhase.postFrameCallbacks;
      final List<FrameCallback> localPostFrameCallbacks =
          List<FrameCallback>.from(_postFrameCallbacks);
      _postFrameCallbacks.clear();
      for (final FrameCallback callback in localPostFrameCallbacks)
        _invokeFrameCallback(callback, _currentFrameTimeStamp!);
    } finally {
      _schedulerPhase = SchedulerPhase.idle;
      Timeline.finishSync(); // end the Frame
      assert(() {
        if (debugPrintEndFrameBanner)
          debugPrint('▀' * _debugBanner!.length);
        _debugBanner = null;
        return true;
      }());
      _currentFrameTimeStamp = null;
    }
  }
  void addPersistentFrameCallback(FrameCallback callback) {
    _persistentCallbacks.add(callback);
  }
  
  mixin RendererBinding on BindingBase, ServicesBinding, SchedulerBinding, GestureBinding, SemanticsBinding, HitTestable {
  @override
  void initInstances() {
    ...
    addPersistentFrameCallback(_handlePersistentFrameCallback);
    ...
  }
  void _handlePersistentFrameCallback(Duration timeStamp) {
    drawFrame();
    _scheduleMouseTrackerUpdate();
  }
  
}
///widgets/binding.dart
@override
  void drawFrame() {
    ...
    try {
      if (renderViewElement != null)
      ///先rebuild, 见3.2
        buildOwner.buildScope(renderViewElement);
      ///后绘制, 见3.3
      super.drawFrame(); 
      buildOwner.finalizeTree();
    } finally {
      assert(() {
        debugBuildingDirtyElements = false;
        return true;
      }());
    }
    ...
  }  

3.2 刷新build()

void buildScope(Element context, [ VoidCallback callback ]) {
    ...
    while (index < dirtyCount) {
        ...
        _dirtyElements[index].rebuild();
    }
    ...
  }
  void rebuild() {
    ...
    performRebuild();
  }

performRebuild具体执行方法,取决于相应的Element子类,这里以ComponentElement为例

@override
  void performRebuild() {
    Widget built;
    try {
      ///调用子类的build方法!!!!!!!
      built = build();
    } catch (e, stack) {
      ...
    } finally {
      _dirty = false;
    }
    try {
      _child = updateChild(_child, built, slot);
      assert(_child != null);
    } catch (e, stack) {
      _child = updateChild(null, built, slot);
    }
  }

3.3 drawFrame (rendering/binding.dart )

在这里插入图片描述

@protected
  void drawFrame() {
    assert(renderView != null);
    ///更新需要计算其布局的渲染对象,
    ///在此阶段计算每个渲染对象的大小和位置,
    ///渲染对象可能会弄脏其绘画或者合成状态,这个过程可能还会调用到build过程。
    pipelineOwner.flushLayout();
    ///pipelineOwne更新具有脏合成位的任何渲染对象,
    ///在此阶段每个渲染对象都会了解其子项是否需要合成。
    ///在绘制阶段使用此信息选择如何实现裁剪等视觉效果。
    ///如果渲染对象有一个自己合成的子项,它需要使用布局信息来创建裁剪,以便将裁剪应用于已合成的子项
    pipelineOwner.flushCompositingBits();
    ///访问需要绘制的任何渲染对象,在此阶段,渲染对象有机会将绘制命令记录到[PictureLayer],并构建其他合成的[Layer];
    pipelineOwner.flushPaint();
    if (sendFramesToEngine) {
      ///执行render()将layer树发送给GPU线程
      renderView.compositeFrame(); // this sends the bits to the GPU
      ///编译渲染对象的语义,并将语义发送给操作系统;
      pipelineOwner.flushSemantics(); // this also sends the semantics to the OS.
      _firstFrameSent = true;
    }
  }

/// Uploads the composited layer tree to the engine.
  ///
  /// Actually causes the output of the rendering pipeline to appear on screen.
  void compositeFrame() {
    Timeline.startSync('Compositing', arguments: timelineArgumentsIndicatingLandmarkEvent);
    try {
      final ui.SceneBuilder builder = ui.SceneBuilder();
      final ui.Scene scene = layer!.buildScene(builder);
      if (automaticSystemUiAdjustment)
        _updateSystemChrome();
      _window.render(scene);
      scene.dispose();
      assert(() {
        if (debugRepaintRainbowEnabled || debugRepaintTextRainbowEnabled)
          debugCurrentRepaintColor = debugCurrentRepaintColor.withHue((debugCurrentRepaintColor.hue + 2.0) % 360.0);
        return true;
      }());
    } finally {
      Timeline.finishSync();
    }
  }
///window.dart
  void render(Scene scene) native 'PlatformConfiguration_render';

4.1 GPU线程

在UI线程执行到compositeFrame()经过多层调用,将渲染任务交给GPU线程来执行. 使用 Skia 库,将 Layer tree进行组合, 生成纹理, 使用 OpenGL 的接口向 GPU 提交渲染内容进行光栅化与合成, 最终显示到屏幕上.

在这里插入图片描述

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Flutter中,setState()方法是用于更新widget状态的。当widget的状态发生改变时,Flutter会创建一个新的widget,并将其与之前的widget进行比较,然后进行重建。通过使用setState()方法,我们可以告诉Flutter重新构建当前widget的子树。 这个方法非常简单,它只是将一个回调函数放入队列中,在下一帧中调用它,从而重新构建widget子树。这个方法是实现Flutter中高效UI更新的重要手段。&lt;span class=&quot;em&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;em&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;em&quot;&gt;3&lt;/span&gt; #### 引用[.reference_title] - *1* *2* [fluttersetState详细分析以及性能优化](https://blog.csdn.net/qq_28563283/article/details/130215555)[target=&quot;_blank&quot; data-report-click={&quot;spm&quot;:&quot;1018.2226.3001.9630&quot;,&quot;extra&quot;:{&quot;utm_source&quot;:&quot;vip_chatgpt_common_search_pc_result&quot;,&quot;utm_medium&quot;:&quot;distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1&quot;}}] [.reference_item style=&quot;max-width: 50%&quot;] - *3* [flutter局部刷新的实现示例](https://download.csdn.net/download/weixin_38673548/14878234)[target=&quot;_blank&quot; data-report-click={&quot;spm&quot;:&quot;1018.2226.3001.9630&quot;,&quot;extra&quot;:{&quot;utm_source&quot;:&quot;vip_chatgpt_common_search_pc_result&quot;,&quot;utm_medium&quot;:&quot;distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1&quot;}}] [.reference_item style=&quot;max-width: 50%&quot;] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值