RepaintBoundary
实现方式:直接使用RepaintBoundary小部件
- RepaintBoundary子树repaint的时候,只有RepaintBoundary子树会被repaint,不影响父级和同级的其他子树
- 如果父widget repaint,则RepaintBoundary子树也会repaint
- 如果非RepaintBoundary子树repaint,则也会引起父widget repaint,但是同级的RepaintBoundary不会repaint
如下图所示,
- one或者two repaint的时候只有其自身repaint,不影响bottom和其他同级
- three repaint的时候,bottom也会repaint,但是one和two不会repaint
- bottom repaint的时候,one、two、three都会repaint
RelayoutBoundary
实现方式:使用Container或者SizedBox,设定固定宽高,因为Container或者SizedBox底下都是用了RenderConstrainedBox(RenderObject类),如果设置了固定宽高,则constraints.isTight为true,从而relayoutBoundary = this
renderObject在layout阶段做了Relayout boundary的优化,当子树进行relayout时,满足下面三种中的一种
- parentUsesSize == false
- sizedByParent == true
- constraints.isTight
那么该renderObject设置为Relayout boundary,也就是该renderObject的重新layout不触发parent的layout,一般情况下开发人员不需要关心Relayout boundary,除非是使用CustomMultiChildLayout
if (!parentUsesSize || sizedByParent || constraints.isTight || parent is! RenderObject) {
relayoutBoundary = this;
} else {
final RenderObject parent = this.parent;
relayoutBoundary = parent._relayoutBoundary;
}
.........
if (_relayoutBoundary != null && relayoutBoundary != _relayoutBoundary) {
// The local relayout boundary has changed, must notify children in case
// they also need updating. Otherwise, they will be confused about what
// their actual relayout boundary is later.
visitChildren((RenderObject child) {
child._cleanRelayoutBoundary();
});
}
_relayoutBoundary = relayoutBoundary;
void markNeedsLayout() {
....
if (_relayoutBoundary != this) {
markParentNeedsLayout();
}
....
}
由以上源码可知,RenderObject中,relayoutBoundary不是自己就是parent。如果是自己,当layout的时候就不会要求parent layout;如果不是自己,当layout的时候就会要求parent layout。