Flutter源码版本为1.12.13
用做简单的例子来讲,这个用户布局只有一个TextView
1 2 3 4
| void main() => runApp( Text("你好", textDirection: TextDirection.ltr), );
|
首先来看runApp()方法:
1 2 3 4 5
| void run(Widgetr app){ WidgetsFultterBinding.ensureInitialized() ..scheduleAttachRootWidget(app) ..scheduleWarmUpFrame(); }
|
- Step1.前置环境,主要是在WidgetsFultterBinding.ensureInitialized()
首先来看WidgetsFultterBinding的定义,这个类从右WidgetBinding往左GestureBinding进行初始化,下面只罗列关键的一些初始化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
| class WidgetFlutterBinding extends BindingBase with GestureBinding, ServiceBinding, ScheduleBinding, PaintingBinding, SemanticsBinding, RenderBinding, WidgetBinding{ ... }
@WidgetBinding mixin WidgetBinding{ BuildOwner _buildOwner;
void initInstances(){ _buildOwner = BuildOwner(); } }
@RenderBinding mixin RenderBinding{ PipelineOwner _pipelineOwner; void initInstance(){ _pipelineOwner = PipelineOwner(...); initRenderView(); addPersistentFrameCallback(_handlePersistentFrameCallback); } void initRenerView(){ render = Render(...); render.prepareInitialFrame(); } set renderView(RenderView value){ _pipelineOwner.rootNode = value; } }
@PipelineOwner class PipelineOnwer{ AbstractNode _rootNode; set rootNode(AbstractNode value){ _rootNode?.attach(this); } }
@RendView void prepareInitialFrame(){ scheduleInitialLayout(); sceduleInitialPaint(_updateMatricesAndCreateNewRootLayer()); }
void addPersistentFrameCallback(FrameCallback callback){ _persistentCallbacks.add(callback); }
void _handlePersistentFrameCallback(Duration timeStamp){ drawFrame(); }
|
至此,需要的前置工作都完成了,生成了一个PipelineOwner与RenderView并且互相持有。创建了一个BuildOnwer,在_persistentCallbacks中注册了回调函数_handlePersistentFrameCallback(),最终调用到drawFrame();
- Step2 . scheduleAttachRootWidget(Widget)@WidgetBinding
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
| void scheduleAttachRootWidget(Widget rootWidget){ Timer.run((){ attachRootWidget(rootWidget); }); }
Element get renderViewElement => _renerViewElement; Element _renderViewElement;
void attachRootWidget(Widget rootWidget){ //这里先生成一个RenderObjectToWidgetAdapter<Render>对象,再调用attachToRenerTree()生成一个Element,该Element为根 _renderViewElement = RenderObjectToWidgetAdapter<Render>( container: renderView, chhild:rootWidget, ).attachToRenderTree(buildOwner, renderViewElement); }
@RenderObjectToWidgetAdapter<Render> class RenderObjectToWidgetAdapter<T extends RenderObject> extends RenderObjectWidget{ //就是用户自定义的Widget final Widget child; //就是RenderView对象 final RenderObjectWithChildMixin<T> container; RenderObjectToWidgetElement<T> createElement() => RenderObjectToWidgetElement<T>(this); RenderObjectWithChildMixin<T> createRenderObject(BuildContext context) => container; //重点 RenderObjectToWidgetElement<T> attachToRenderTree(BuildOwner owner,[RenderObjectToWidgetElement<T> element]){ if(element == null){ //命中,入参element此时为null //lockState()@BuildOwner会调用callback owner.lockState((){ //可以看到,element会RenderObjectToWidgetElement<RenderBox>对象,并且内部的widget为this,即RenderObjectToWidgetAdapter<RenderBox> element = createElement(); element.assignOwner(owner); }); owner.buildScope(element, (){ //调用mount()函数入参均为0,这个方法在第三步讨论 element.mount(null,null); }); }else{ ... } return element } }
|
- Step3. mount(null,null)@RenderObjectToWidgetElement
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
| @RenderObjectToWidgetElement void mount(Element parent, dynamic newSlot){ super.mount(parent,new Slot); _rebuild(); }
@RenderObjectElement class RenderObjectElement{ RenderObject _renderObject; void mount(Element parent, dynamic newSlot){ //对于REnderObjectToWidgetElement,widget就是RenderObjectToWidgetAdapter //于是返回的_renderObject就是RenderView _renderObject = widget.createRenderObject(this); attachRenderObject(newSlot); } void attachRenderObject(dynamic newSlot){ //重点,是在这里进行生成RenderObject树的 //_findAncestoreRenderObjectElement是向上寻找最近的RenderObjectElement,只有该Element才有RenderObject, //找到后将其作为当前RenderObject的parent,属于递归 //在这里是根Element,所以不会执行 _ancestoreRenderObjectElement = _findAncestoreRenderObjectElement(); //由子类实现,一般来说是把自身挂到最近的父RenderObject上,递归生成RenderObject树 _ancestoreREnderObjectElement?.insertChildREnderObject(renderObject, newSlot); } RenderObjectElement _findAncestoreRenderObjectElement(){ Element ancestore = _parent; while(ancestore!=null && ancestore is! RenderObjectElement){ ancestore = ancestore._parent; } return ancestore; } }
//也是很关键,在这里方法里会进行递归,构造Widget树,Element树,RenderObject树 void _rebuild(){ //在这里,_child为null,widget为RenderObjectToWidgetAdapter<BoxRender>, //于是widget.chil即为我们自定义的Widget,在这里就是Text() _child = updateChild(_child, widget.child, _rootChildSlot); }
Element updateChild(Element child, Widget newWidget, dynamic newSlot){ //因为child为null,于是直接是最后一步 return inflateWidget(newWidget, newSlot); }
Element inflateWidget(Widget widget, dynamic newSlot){ //创建子,即Text的Element //由具体的子类实现 final Element newChild=newWidget.createElement(); //该方法会递归构造Widget树,Element树,RenderObject树 //该方法由具体的子类实现 newChild.mount(this, newSlot); //返回子的Element,并且挂载在当前RenderObjectToWidgetElement的_child上 return newChild; }
|
于是,我们拥有了一个RenderView和Pipeline对象,互相持有。
一个RenderObjectToWidgetElement,其_child为Text(自己实现的Widget).createElement()对象,其widget成员变量为RenderObjectToWidgetAdapter,其_renderObject变量为RenderView
一个RenderObjectToWidgetAdapter<BoxRender对象>,其child为用户自定义的Widget,container为RenderView。该对象如其名,Adapter,属于一个桥接的功能。
我们的定义的子类的Text,因此要去Text的源码里面看了,之前分析到newWidget.createElement()/newChild.mount(this,newSlot).【newWidget为Text,this指向RenderObjectToWidgetElement,后面可以知道newChild为newWidget调用crateElement()创建的StatelessElement对象】
首先来看Text类的继承结构
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99
| Text -> StatelessWidget -> Widget //Text没有重写createElement(),该方法在StatelessWidget实现
@StatelessWidget abstract class StatelessWidget extends Widget{ //执行完之后,Text创建了一个StatelessElement,其内部的widget即为Text本身, //并且将该StatelessElement作为RenderObjectToWidgetElement<BoxRender>的_child进行挂载 StatelessElement createElement() => StatelessElement(this); }
//StatelessElement继承自ComponentElement
@ComponentElement abstract class ComponentElement extends Element{ //在这里parent为根RenderObjectToWidgetElement void mount(Element parent, dynamic newSlot){ //super.mount()将RenderObjectToWidgetElement最为parent进行挂载 //将其owner作为本身的owner即BuildOwner,同时更新树的深度 super.mount(parent, newSlot); _firstBuild(); } void _firstBuild(){ rebuild(); } @Element void rebuild(){ ... performRebuild(); } @ComponeneElement void performRebuild(){ Widget build=build(); //这里开始递归调用了,同时_child为null,会执行inflateWidget(), //已经分析过了,在递归挂载 //从下面分析可以知道,这里的build是RichText对象 _child=updateChild(_child, build, slot); } }
@StatelessElement class StatelessElemet extends ComponentElement{ //widgt为Text Widget() => widget.build(this); }
@Text class Text{ Widget build(BuildCOntext context){ Widget result=RichText(...); return result; } }
//于是开始调用RichText的createElement()与 update@Element(); class RichText extends MultiChildRenderObjectWidget{ _MouseREgionElement createElement()=>_MouseRegionElement(this); }
class _MouseRegionElement extends SigleChildRenderObjectElement(){ }
class SingleChildREnderObjectElement extends RenderObjectElement{ void mount(Element parent, dynamic newslot){ super.mount(parent, newSLot) _child = updateChild(_child, widget.child, null); } }
class RenderObjectElement{ void mount(Element element, dynamic, newSlot){ super.mount(parent, newSlot); _renderObject = widget.createRenderObject(this); //在这里挂载RenderObject树 attachREnderObject(newSlot); } void attachRenderObject(dynamic newSlot){ //向上寻找最近的RenderObject,在这里就是REnderObjectToWidgetElement<BoxRender> _ancestorRenderObjectElement=_findAncestoreRenderObjectElement(); //父类实现 _ancestorRenderObjectElement?.insertChildRenderObject(renderObject, newSLot); } @RenderBojectToWidgetElement void insertChildRenderObject(RenderObject child, dynamic slot){ //将RichText创建的RenderObject挂载,最为child renderObject.child = child; } //来看看挂载的RenderObject是什么 @TextRich RenderParagaph createRenderObject(BuildContext context){ return RenderParagraph(); } }
|
可以看到,在向下递归的过程中并且会将子节点的Element挂载到当前节点的Element生成Element树,如果当前节点Element为RenderObjectElement的子类,则在mount()的过程中,会将该节点的RenderObject挂载到父RenderObjectElement上,生成RenderObject树。
要注意的是Widget其实不会生成一颗树,在Widget的属性类别也没有【Widget child】这个属性,在代码中也找不到树的生成,从父Widget也无法直接访问到子Widget,从子Widget也无法访问到父Widget。那么我们说的Widget树到底是什么东西。
在Flutter中,一般树特指Element树,因为每个Element都持有其对应的Widget,并且可以根据Element树生成对应的RenderObject树。
下面就开始进行渲染的过程了
下面要分析的是scheduleWarmUpFrame()函数【runApp()】
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82
| @ScheduleBinding void scheduleWarmUpFrame(){ Timer.run((){ //不用关注 handleBeginFrame(null); }); Timer.run((){ //重点 handleDrawFrame(); }); //这里就是调用engine进行绘制 //scheduleFrame()@window 属于engine的native方法 scheduleFrame(); }
void handleDrawFrame(){ //设定目前正在进行persistentCallbacks状态 _schedulerPhase = SchedulePhase.phersistentCallbacks; //最上面分析过,最重要的一个callback在RenderBinding构造的时候添加了 //即doFrame()@RenderBinding for(FrameCallback callback in _persistemtCallbacks){ _invokeFrameCallback(callback, _currentFrameTimeStamp); } ... }
@RenderBing void drawFrame(){ //布局 pipelineOwner.flushLayout(); //合成 pipelineOwner.flushCompositingBits(); //绘制 pipelineOwner.flustPaint(); render.conpositeFrame(); pipelineOwner.flushSemantics(); }
void flushLayout(){ //scheduleInitialLayout()@RenderView的时候,RenderView将自己加入了PipelineOwner._nodesNeedingLayout //遍历_nodesNeedingLayout node._layoutWidhResize(); }
@RenderObject void _layoutWidhResize(){ performLayout(); ... }
@RenderView void performLayout(){ //对于RenderView来说,其Child就是在挂载RenderObject过程中挂载的, //在这里是RenderParagraph child.layout(BoxConstraints.tight(_size); }
@RenderObject void layout(Constraints constraints, {bool parentUserSize=false}){ RenderObject relayoutBoundary; //this是RenderParagraph relayoutBoundary = this //根据子类具体实现,也是一般推荐子类只实现performLayout()的理由 performLayout(); }
@RenderParagraph void performLayout(){ _layoutChildern(constraints); _LayoutTextWithConstraints(constraints); }
void _layoutChildren(){ RenderBox child = firstChild; whild(child !=null){ //遍历执行子类的layout child.layout(...); child = childAfter(child); } }
|
在RenderObject树进行向下遍历Layout后,layout的操作就算完成了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
| @PipelineOwner voud flushPaint(){ PaintingContext.repaintCompositedChild(node); }
@PaintingContext static void repaintCompositedChild(RenderObject child, {bool debugAlsoPaintParent = false}){ //同理,这里的child是RenderView _repaintCompositeChild(child); }
static void _repaintCompositedChild(Render child){ child._paintWithContext(childContext, Offset.zero); } @RenderObject void _paintWithContext(PaintingContext context, Offset offset){ paint(context, offset); }
@RenderView void paint(PaintingContext context, Offset offset){ //在这里,child就是RenderParagraph context.paintChild(child,offset); }
@PaintingContext void paintChild(RenderObject child, Offset offset){ //在这里,child就是RenderParagraph,同上,会到底调用paint() child._paintWithContext(child,offset); }
@RenderParagraph void paint(PaintingContext context, Offset offset){ //自身的绘制逻辑 while(child != null && childIndex < _textPainter.inlinePlaceholderBoxes.length){ //执行child,递归调用 context.paintChild(child.offset); } }
|
于是,会递归RenderObject树,进行perform(),再递归RenderObject,进行paint();
绘制完成后就可以调用engine进行绘制了。