Flutter RendererBinding作用源码分析

 更新时间:2022年12月12日 14:58:07   作者:WeninerIo  
这篇文章主要为大家介绍了Flutter RendererBinding作用和内部一些重要的类源码分析,希望此文能给你带来收获.有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

分析

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的资料请关注脚本之家其它相关文章!

相关文章

  • iOS 防止按钮多次点击造成多次响应的方法

    iOS 防止按钮多次点击造成多次响应的方法

    这篇文章主要介绍了iOS 防止按钮多次点击造成多次响应的方法的相关资料,这里对多次点击造成的响应提供了解决办法,需要的朋友可以参考下
    2016-11-11
  • IOS 的弹性滚动解决方案

    IOS 的弹性滚动解决方案

    所谓弹性滚动就是指在翻动长页面手指离开时,由慢到块,由快到慢的过度。这篇文章主要介绍了IOS 的弹性滚动解决方案,需要的朋友可以参考下
    2016-10-10
  • iOS创建对象的不同姿势详解

    iOS创建对象的不同姿势详解

    这篇文章主要介绍了iOS创建对象的不同姿势,文中介绍的很详细,对大家具有一定的参考价值,有需要的朋友们下面来一起学习学习吧。
    2017-02-02
  • 为按钮位置配置不同的IOS背景

    为按钮位置配置不同的IOS背景

    这篇文章主要介绍了为按钮位置配置不同的IOS背景,面对多个按钮如何配置不同的IOS背景,需要的朋友可以参考下
    2015-07-07
  • NSURLSession跨域重定向透传HTTP Header问题解决

    NSURLSession跨域重定向透传HTTP Header问题解决

    这篇文章主要为大家介绍了NSURLSession跨域重定向透传HTTP Header问题解决方案,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-11-11
  • MacOS系统下Unity启动黑屏的解决方法

    MacOS系统下Unity启动黑屏的解决方法

    最近发现了一个问题,unity一打开就黑屏,通过查找相关的资料终于解决了,所以下面这篇文章主要给大家介绍了关于在MacOS系统下Unity启动黑屏的解决方法,文中通过示例代码介绍的非常详细,需要的朋友可以参考下。
    2018-01-01
  • Xcode中代码注释编写的一些小技巧

    Xcode中代码注释编写的一些小技巧

    如何在 Xcode 中编写规范注释,规范注释可以在Xcode的快速帮助检查器(quickheliector)中显示,这篇文章主要给大家介绍了关于Xcode中代码注释编写的一些小技巧,需要的朋友可以参考下
    2021-10-10
  • iOS 8使用UIBlurEffect实现毛玻璃特效

    iOS 8使用UIBlurEffect实现毛玻璃特效

    这篇文章主要为大家详细介绍了iOS 8使用UIBlurEffect类和UIVisualEffectView类实现毛玻璃特效,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-05-05
  • iOS实现去除html标签的方法汇总

    iOS实现去除html标签的方法汇总

    相信大家在做网站的时候,经常会遇到去除html标签的问题,下面这篇文章主要给大家总结介绍了关于iOS如何实现去除html标签的一些方法,文中通过示例代码介绍的非常详细,需要的朋友可以参考借鉴,下面来一起看看吧。
    2017-10-10
  • iOS应用开发中使用NSLocale类实现对象信息的本地化

    iOS应用开发中使用NSLocale类实现对象信息的本地化

    这篇文章主要介绍了iOS应用开发中使用NSLocale类实现对象信息的本地化的方法,能够将时间和货币等格式化为与系统本地设置相同的偏好,需要的朋友可以参考下
    2016-05-05

最新评论