这是我参与11月更文应战的第27天,活动详情检查:2021最后一次更文应战
1. 烘托原理
在Flutter实战中写道,Flutter 框架的布局、制作的处理流程是这样的:
- 依据 Widget 树生成一个 Element 树,Element 树中的节点都承继自 Element 类。
- 依据 Element 树生成 Render 树(烘托树),烘托树中的节点都承继自RenderObject 类。
- 依据烘托树生成 Layer 树,然后上屏显现,Layer 树中的节点都承继自 Layer 类。 真正的布局和烘托逻辑在 Render 树中,Element 是 Widget 和 RenderObject 的粘合剂,能够理解为一个中间署理。
2. Render 树
不是一切的Widget 都会生成render,比方Container就不会创立RenderObject。
只要承继自RenderObject类的目标才会生成RenderObject目标,比方Column,这样就会被烘托引擎直接烘托。
在renderObject里边有两个重要的办法便是createElement 和 createRenderObject,这两个办法都是抽象办法,那么在子类中应该有相应的完成。
先来看createRenderObject办法,在flex中找到了createRenderObject的完成。createRenderObject里边仅仅做了一件事便是创立了RenderFlex
点进去看到RenderFlex承继自RenderBox。
在点进去看到RenderBox承继自RenderObject。
所以createRenderObject也便是回来了一个RenderObject目标。那么也便是说,并不是一切的Widget都会独立烘托,只要完成了createRenderObject而且回来了RenderObject目标的才会被独立烘托。
3. Element 树
一切的Widget都会创立一个Element目标。看到之前的createElement办法。
RenderObjectElement createElement();
看一下子类是如何完成createElement办法的。这儿在MultiChildRenderObjectWidget找到了办法的完成,这儿回来了一个MultiChildRenderObjectElement目标。
MultiChildRenderObjectElement承继自RenderObjectElement。
接下来看StatelessWidget 里边是否有完成createElement办法。进去后发现是有的。
再来看一下StatefulWidget,也是有的。
而这儿也能够看到,一切承继自Widget的,都有element。所以这儿能够得知,Widget树和element树是一一对应的联系。
在StatefulWidget里边的createElement打下断点后运行。
这儿第一个调用这个办法的是material app。
如果是StatelessWidget里边的createElement的话那么就应该是MyApp。
往下走一步之后来到了这儿,看到有调用一个mount办法。
点进去之后看到注释,大概便是说当有一个新的element被增加的时分,mount办法都会被调用一次。也便是说当有一个新的Widget被创立的时分,mount办法都会被调用一次。
接下来看renderObject里边的mount办法。 在MultiChildRenderObjectWidget里边的createElement办法打下断点。
点击下一步发现也是有调用mount办法的。
而createRenderObject在mount办法之后也便是createElement办法之后。所以过程是Widget树 —— Element树 —— Render树
在createRenderObject下面一个函数mount里边就会调用createRenderObject创立RenderObject。
4. Element 和 Widget 的联系
StatelessWidget中createElement的是StatelessElement。
StatelessElement 承继自ComponentElement
来到ComponentElement,看到了这儿有mount办法,在mount里边调用了_firstBuild办法。
_firstBuild里边则调用了rebuild。
rebuild里边也有一堆判断,然后调用了performRebuild办法。
看到performRebuild仅仅一个界说。
接下来去componentElement里边看performRebuild办法。看到这儿有个built变量,而且等于build办法
看到build仍是一个办法的界说。
看到StatelessElement里边的build办法直接回来widget的build办法的回来值,而这个widget便是StatelessWidget。
那么也便是说,当创立一个StatelessWidget目标的时分,就会
- 调用createElement办法,
-
- 创立componentElement目标,调用mount办法
- 调用_firstBuild办法
- 调用rebuild办法
- 调用performRebuild办法
- 调用了StatelessElement里边的build办法
- 调用了StatelessWidget目标的build办法进行烘托
这儿证明StatelessElement里边的widget是外面的StatelessWidget目标。 当这儿调用createElement的时分,这儿的this便是StatelessWidget目标。
而在StatelessElement时分,这儿边的widget便是传进来的StatelessWidget目标,而且传给了super。
来到ComponentElement,又传给了ComponentElement的super。
然后看到Element里边接纳到了这个widget,就赋值给了_widget。
- Widget的烘托原理
- 并不是一切的Widget都会被独立烘托!只要承继RenderObjectWidget的才会创立RenderObject目标!
- 在Flutter烘托的流程中,有三颗重要的树!Flutter引擎是针对Render树进行烘托!
- Widget树、Element树、Render树
- 每一个Widget都会创立一个Element目标
- 隐式调用createElement办法。Element加入Element树中,它会创立三种Element
- RenderElement首要是创立RenderObject目标, 承继RenderObjectWidget的Widget会创立RenderElement
- 创立RanderElement
- Flutter会调用mount办法,调用createRanderObject办法
- StatefulElement承继ComponentElement,StatefulWidget会创立StatefulElement
- 调用createState办法,创立State
- 将Widget赋值给state
- 调用state的build办法 而且将自己(Element)传出去,build里面的context 便是Widget的Element !
- StatelessElement承继ComponentElement,StatelessWidget会创立StatelessElement
- 首要便是调用build办法 而且将自己(Element)传出去
- 每一个Widget都会创立一个Element目标
- Widget树、Element树、Render树