flutter_run_app_analyze

2020-09-25  本文已影响0人  Wi1ls努力努力再努力

Flutter源码版本为1.12.13

用做简单的例子来讲,这个用户布局只有一个TextView

void main() => runApp(
    Text("你好",
    textDirection: TextDirection.ltr),
);

首先来看runApp()方法:

void run(Widgetr app){
    WidgetsFultterBinding.ensureInitialized()
        ..scheduleAttachRootWidget(app)
        ..scheduleWarmUpFrame();
}

首先来看WidgetsFultterBinding的定义,这个类从右WidgetBinding往左GestureBinding进行初始化,下面只罗列关键的一些初始化

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();


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
    }
}

@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<BoxRender>,其_child为Text(自己实现的Widget).createElement()对象,其widget成员变量为RenderObjectToWidgetAdapter<BoxREnder>,其_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类的继承结构

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树。


到此,我们在RenderObjectToWidgetElement中就构造好了Element树,RenderObject树,分别对应_child@RenderObjectToWidgetElement, _renderObject@RenderObjectToWidgetElement。

下面就开始进行渲染的过程了


下面要分析的是scheduleWarmUpFrame()函数【runApp()】

@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的操作就算完成了。

@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进行绘制了。

上一篇下一篇

猜你喜欢

热点阅读