当前位置: 代码网 > it编程>App开发>苹果IOS > Flutter RendererBinding作用源码分析

Flutter RendererBinding作用源码分析

2024年05月18日 苹果IOS 我要评论
分析rendererbinding 的作用是负责render tree 和flutter engine之间的连接. 我们在启动app的时候,首先会创建 piplineowner ,然后通过platfo

分析

rendererbinding 的作用是负责render tree 和flutter engine之间的连接. 我们在启动app的时候,首先会创建 piplineowner ,然后通过platformdispatcher去监听屏幕分辨率变化、系统文字大小变化、亮度、语义等等.最后去初始化renderview,根据平台去处理如帧回调、鼠标、web之类的信息.

 void initinstances() {
    super.initinstances();
    _instance = this;
    _pipelineowner = pipelineowner(
      onneedvisualupdate: ensurevisualupdate,
      onsemanticsownercreated: _handlesemanticsownercreated,
      onsemanticsownerdisposed: _handlesemanticsownerdisposed,
    );
    platformdispatcher
      ..onmetricschanged = handlemetricschanged
      ..ontextscalefactorchanged = handletextscalefactorchanged
      ..onplatformbrightnesschanged = handleplatformbrightnesschanged
      ..onsemanticsenabledchanged = _handlesemanticsenabledchanged
      ..onsemanticsaction = _handlesemanticsaction;
    initrenderview();
    _handlesemanticsenabledchanged();
    assert(renderview != null);
    addpersistentframecallback(_handlepersistentframecallback);
    initmousetracker();
    if (kisweb) {
      addpostframecallback(_handlewebfirstframe);
    }
  }

pipelineowner

这里我们着重讲一下pipelineowner, 官方描述中有这么一句话the pipeline owner manages the rendering pipeline., 也就是说 pipelineowner帮我们管理着渲染所需要的. 我们根据pipelineowner调用的顺序依次讲解下它提供的方法.

flushlayout

这个阶段将计算每个渲染对象的大小和位置, 渲染对象可能会在绘制或者compositing state 的时候被标成dirty,这是什么意思呢? 让我们回归到代码中

  // 持有需要被布局的对象
  list<renderobject> _nodesneedinglayout = <renderobject>[];
{
    非release包运行代码忽略
    ...
    try {
      // 如果当前的节点需要合成
      while (_nodesneedinglayout.isnotempty) {
        final list<renderobject> dirtynodes = _nodesneedinglayout;
        _nodesneedinglayout = <renderobject>[];
        for (final renderobject node in dirtynodes..sort((renderobject a, renderobject b) => a.depth - b.depth)) {
          if (node._needslayout && node.owner == this)
            node._layoutwithoutresize();
        }
      }
    } finally {
        ... 
    }
}

代码中可以看到, 如果 _nodesneedinglayout 中对象不为空.说明当前需要被布局,计算其大小.我们可以看到在依次处理节点时,最后一步是执行 _layoutwithoutresize() ,这个方法调用的本质实际上也就是 performlayout(). 那么, performlayout() 做了什么呢? 如果对自定义布局有过了解, 通常我们在实现 performlayout() 的时候.会先去 layout widget . 然后去通过position将widget 定位. 确定好widget在父widget中的相对位置.

flushcompositingbits

这个阶段中, 每个渲染对象都会了解其子对象是否需要合成.在绘制的阶段选择如何实现视觉效果. 这里实际上也就是标记所有的子对象是否需要合成

  void flushcompositingbits() {
    ...
    _nodesneedingcompositingbitsupdate.sort((renderobject a, renderobject b) => a.depth - b.depth);
    for (final renderobject node in _nodesneedingcompositingbitsupdate) {
      if (node._needscompositingbitsupdate && node.owner == this)
        node._updatecompositingbits();
    }
    _nodesneedingcompositingbitsupdate.clear();
   ...
  }

flushpaint

在这个阶段,我们将会真正的绘制出layer

  void flushpaint() {
    ...
    try {
      final list<renderobject> dirtynodes = _nodesneedingpaint;
      _nodesneedingpaint = <renderobject>[];
      // sort the dirty nodes in reverse order (deepest first).
      for (final renderobject node in dirtynodes..sort((renderobject a, renderobject b) => b.depth - a.depth)) {
        ...
        if (node._needspaint && node.owner == this) {
          if (node._layerhandle.layer!.attached) {
            paintingcontext.repaintcompositedchild(node);
          } else {
            node._skippedpaintingonlayer();
          }
        }
      }
      ...
    } finally {
      ...
    }
  }

在绘制的时候将会判断当前的layer是否attached,如果不是attched的状态.则说明当前的layer已经调用detach方法,因此不再需要绘制.所以会跳过绘制,执行 _skippedpaintingonlayer() 的方法. 如果是attached的状态,则需要调用 repaintcompositedchild() 的方法

flushsemantics

最后,如果启用了语义. 这个阶段将会编译渲染对象的语义,这里就不过多介绍了.

initrenderview

如果说还有比较重要的方法需要讲解, 那么就是 initrenderview() 这个方法了.这里将会创建一个 renderview的对象作为renderobject的根 ,同时对它进行初始化.

  void initrenderview() {
    renderview = renderview(configuration: createviewconfiguration(), window: window);
    // 准备第一帧启动渲染通道. 这里只会调用一次.
    renderview.prepareinitialframe();
  }

在 prepareinitalframe() 中, 我们通过 scheduleinitiallayout和scheduleinitialpaint , 安排微事务队列尽可能快的处理layout和paint.

scheduleinitiallayout

在这个阶段,主要是将owner的_nodesneedinglayout 对象中加入这个初始化的renderview.

scheduleinitialpaint

这个阶段中, 我们将_layerhandle 中的layer 赋值成当前layer.并在owner中加入 _nodesneedingpaint .

  void scheduleinitialpaint(containerlayer rootlayer) {
    _layerhandle.layer = rootlayer;
    owner!._nodesneedingpaint.add(this);
  }

今天的rendererbinding源码分析就暂告一个段落了,它主要是负责了测量布局、绘制之类的方法. 作为一个入口还是有了解的必要的, 建议大家有时间可以多看看.

以上就是flutter rendererbinding作用源码分析的详细内容,更多关于flutter rendererbinding的资料请关注代码网其它相关文章!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com