Flutter圈子Flutter

跟我学flutter:细细品Widget(四)Widget 渲染

2022-05-05  本文已影响0人  王二蛋和他的狗

前言

StatelessWidget 和 StatefulWidget 只是用来组装控件的容器,并不负责组件最后的布局和绘制。在 Flutter 中,布局和绘制工作实际上是在 Widget 的另一个子类 RenderObjectWidget 内完成的。
RenderObjectWidget为RenderObjectElement提供配置信息。
RenderObjectElement包装了RenderObject,RenderObject为应用程序提供真正的渲染。

源码

abstract class RenderObjectWidget extends Widget {
 
  const RenderObjectWidget({ Key? key }) : super(key: key);

  @override
  @factory
  RenderObjectElement createElement();

  @protected
  @factory
  RenderObject createRenderObject(BuildContext context);

  @protected
  void updateRenderObject(BuildContext context, covariant RenderObject renderObject) { }

  @protected
  void didUnmountRenderObject(covariant RenderObject renderObject) { }
}

RenderObjectElement 源码

abstract class RenderObjectElement extends Element {
  RenderObject _renderObject;
 
  @override
  void mount(Element parent, dynamic newSlot) {
    super.mount(parent, newSlot);
    _renderObject = widget.createRenderObject(this);
    attachRenderObject(newSlot);
    _dirty = false;
  }
   
  @override
  void update(covariant RenderObjectWidget newWidget) {
    super.update(newWidget);
    widget.updateRenderObject(this, renderObject);
    _dirty = false;
  }
  ...
}

RenderObject 主要处理一些固定的操作,如:布局、绘制和 Hit testing。 与ComponentElement一样RenderObjectElement也是抽象类,不同的是ComponentElement不会直接创建RenderObject,而是间接通过创建其他Element创建RenderObject。

RenderObjectElement主要有三个系统的子类,分别处理renderObject作为child时的不同情况。

  1. LeafRenderObjectElement:叶子渲染对象对应的元素,处理没有children的renderObject。
  2. SingleChildRenderObjectElement:处理只有单个child的renderObject。
  3. MultiChildRenderObjectElement: 处理有多个children的渲染对象

有时RenderObject的child模型更复杂一些,比如多维数组的形式,则可能需要基于RenderObjectElement实现一个新的子类。

RenderObjectElement 充当widget与renderObject之间的中介者。需要进行方法覆盖,以便它们返回元素期望的特定类型,例如:

class FooElement extends RenderObjectElement {                                       
                                                                                    
 @override                                                                          
 Foo get widget => super.widget; 
                                                   
@override                                                                          
RenderFoo get renderObject => super.renderObject;                                  
                                                                          
}               

widget返回Foo,renderObject 返回RenderFoo

系统常用组件与RenderObjectElement:

常用组件 Widget(父级) Element
Flex/Wrap/Flow/Stack MultiChildRenderObjectWidget MultiChildRenderObjectElement
RawImage(Imaget)/ErrorWidget LeafRenderObjectWidget LeafRenderObjectElement
Offstage/SizedBox/Align/Padding SingleChildRenderObjectWidget SingleChildRenderObjectElement

RenderObject源码

abstract class RenderObject extends AbstractNode with DiagnosticableTreeMixin implements HitTestTarget {
  ...
  void layout(Constraints constraints, { bool parentUsesSize = false }) {...}
  
  void paint(PaintingContext context, Offset offset) { }
}

布局和绘制完成后,接下来的事情就交给 Skia 了。在 VSync 信号同步时直接从渲染树合成 Bitmap,然后提交给 GPU。

文章参考:https://www.jianshu.com/p/c3de443a70c7

上一篇 下一篇

猜你喜欢

热点阅读