Flutter圈子Flutter for iOSFlutter教程网

Flutter视图的Layout与Paint

2018-12-05  本文已影响27人  e618211d6873

本文目的

目录结构

Flutter的绘图原理和UI的基本流程

Widget在Flutter绘图时的作用

在这之前,我们要先了解几个概念

Widget
Element
RenderObject
Widget-Element-RenderObject .jpg

而以上这三个概念也对应着三种树结构:模型树、呈现树、渲染树。
在解释他们的概念和关系以后,我们已经认识到RenderObject的重要性,因为以下Layout、Paint包括relayout boundary和repaint boundary都是在这里发生的。

一般一个Widget被更新,那么持有该 Widget的节点的Element会被标记为dirtyElement,在下一次更新界面时,Element树的这一部分子树便会被触发performRebuild,在Element树更新完成后,便能获得RenderObject树,接下来会进入Layout和Paint的流程。

Layout

constraints.isTight

什么是isTight呢?用BoxConstraints为例


BoxConstraints.jpeg

它有四个属性,分别是minWidth,maxWidth,minHeight,maxHeight

所以isTight就是强约束,Widget的size已经被确定,里面的子Widget做任何变化,size都不会变。那么从该Widget开始里面的任意子Wisget做任意变化,都不会对外有影响,就会被添加Relayout boundary(说添加不科学,因为实际上这种情况,它会把size指向自己,这样就不会再向上递归而引起父Widget的Layout了)

parentUsesSize == false

实际上parentUsesSize与sizedByParent看起来很像,但含义有很大区别
parentUsesSize表示父Widget是否要依赖子Widget的size,如果是false,子Widget要重新布局的时候并不需要通知parent,布局的边界就是自身了。

sizedByParent == true

sizedByParent表示当前的Widget虽然不是isTight,但是通过其他约束属性,也可以明确的知道size,比如Expanded,并不一定需要明确的size。

通过查看RenderObject-1579行,当然可以看到Layout的实现

void layout(Constraints constraints, { bool parentUsesSize = false }) {
    ...
    if (!parentUsesSize || sizedByParent || constraints.isTight || parent is! RenderObject) {
      relayoutBoundary = this;
    } else {
      final RenderObject parent = this.parent;
      relayoutBoundary = parent._relayoutBoundary;
    }
    ...
}

通过Layout可以看到,flutter为了提高效率所做的努力,那作为开发者可以直接使用relayout boundary吗?
一般情况是不可以的,但是如果当你决定要自定义一个Row的时候,肯定是要使用它的。但是你可以间接的利用上面的三个条件来使你的Widget树某些地方拥有relayout boundary。

Paint

总结

relayout boundary和repaint boundary都是Flutter为了提高绘图性能而做的努力。通常开发者可以使用RepaintBoundary组件来提高应用的性能,也可以根据relayout boundary的几个规则来使relayout boundary生效,从而提高性能。

参考

Flutter's Rendering Pipeline
深入了解Flutter界面开发(强烈推荐)
Flutter 渲染流水线浅析
Flutter原理与实践
Flutter中的布局绘制流程简析
Flutter Dart Framework原理简解

上一篇 下一篇

猜你喜欢

热点阅读