渲染原理¶
不变的就定义常量const。
核心渲染:增量渲染。
flutter修改UI,增量渲染,哪个widget变了就渲染谁。所以不变的定义const。
flutter整个页面是一个树,不变的不用管,只会渲染(新建)树中改变的节点widget,并不是全部都渲染。没有图层,只有一层页面。想要改变某一个控件的值,直接新创建一个widget对象控件,把原来的替换掉。
iOS有一层一层的控件。
三个树¶
- Widget树
- Element树
- Render树
引擎直接渲染Widget树会非常消耗性能。因为Widget会经常发生变化,就会build。
flutter渲染的是RenderObject树。与渲染有关的是Render树。
不是所有的Widget都会生成Render树,所以并不是所有的Widget都会显示到屏幕上。
Container继承StatelessWidget,StatelessWidget继承Widget,不会创建RenderObject对象。
只有继承RenderObject才会创建RenderObject。如布局Row、Column继承Flex,Flex继承RenderObjectWidget。Flex重写了父类的createRenderObject。
abstract class RenderObjectWidget extends Widget {
const RenderObjectWidget({ Key? key }) : super(key: key);
/// RenderObjectWidgets always inflate to a [RenderObjectElement] subclass.
@override
@factory
RenderObjectElement createElement();
@protected
@factory
/// 抽象方法,子类去实现
RenderObject createRenderObject(BuildContext context);
///省略代码
}
所有继承Widget的都会创建Element对象。Widget和Element一一对应。没有继承Render的也有createElement。
Element会调用mount方法。如果部件是继承RenderObjectWidget对象,RenderObjectElement的mount方法里面就会调用widget.createRenderObject
方法。
Element把Widget和Render关联在一起。
Element相当于中间层。
Widget¶
StatelessWidget¶
abstract class StatelessWidget extends Widget {
const StatelessWidget({ Key? key }) : super(key: key);
@override
//创建element对象
StatelessElement createElement() => StatelessElement(this);//this就是widget
@protected
Widget build(BuildContext context);
}
调用StatelessWidget的build方法
class StatelessElement extends ComponentElement {
/// Creates an element that uses the given widget as its configuration.
StatelessElement(StatelessWidget widget) : super(widget);
@override
StatelessWidget get widget => super.widget as StatelessWidget;
@override
Widget build() => widget.build(this);//调用StatelessWidget的build方法
@override
void update(StatelessWidget newWidget) {
super.update(newWidget);
assert(widget == newWidget);
_dirty = true;
rebuild();
}
}
ComponentElement里面会调用mount方法,然后一层一层的调用,最终拿出widget对象调用build方法。
abstract class ComponentElement extends Element {
/// Creates an element that uses the given widget as its configuration.
ComponentElement(Widget widget) : super(widget);
Element? _child;
bool _debugDoingBuild = false;
@override
bool get debugDoingBuild => _debugDoingBuild;
@override
void mount(Element? parent, Object? newSlot) {
super.mount(parent, newSlot);
assert(_child == null);
assert(_lifecycleState == _ElementLifecycle.active);
_firstBuild();
assert(_child != null);
}
void _firstBuild() {
rebuild();
}
@override
@pragma('vm:notify-debugger-on-exception')
void performRebuild() {
if (!kReleaseMode && debugProfileBuildsEnabled)
Timeline.startSync('${widget.runtimeType}', arguments: timelineArgumentsIndicatingLandmarkEvent);
/// Subclasses should override this function to actually call the appropriate
/// `build` function (e.g., [StatelessWidget.build] or [State.build]) for
/// their widget.
@protected
Widget build();
/// 省略代码
}
Element
abstract class Element extends DiagnosticableTree implements BuildContext {
/// Creates an element that uses the given widget as its configuration.
///
/// Typically called by an override of [Widget.createElement].
Element(Widget widget)
: assert(widget != null),
_widget = widget;//_widget变量赋值
/// 省略代码
}
创建widget会调用createElement方法创建element,element创建完之后会调用外面widget的build,并把element作为context传出去。
总结:
- statelessWidget会创建Element
- Element创建会调用mount方法
- mount方法会调用widget的build方法进行渲染,并且将Element自己传出去(BuildContext context)。
StatefulWidget¶
widget和state共用一个element
abstract class StatefulWidget extends Widget {
const StatefulWidget({ Key? key }) : super(key: key);
@override
StatefulElement createElement() => StatefulElement(this);//this就是widget
@protected
@factory
State createState(); // ignore: no_logic_in_create_state, this is the original sin
}
class StatefulElement extends ComponentElement {
/// Creates an element that uses the given widget as its configuration.
/// 创建element对象,创建的时候多了一个创建State并把state保存
StatefulElement(StatefulWidget widget)
: _state = widget.createState(),
super(widget) {
/// assert
state._element = this;//widget和state公用一个element
state._widget = widget;//把widget保存到state的_widget
assert(state._debugLifecycleState == _StateLifecycle.created);
}
@override
Widget build() => state.build(this);//state的build this是element
/// 省略代码
}
总结:
在Flutter渲染的流程中,有三棵树,Flutter引擎渲染是针对Render树中的对象进行渲染。
每一个widget创建出来都会创建一个Element对象
调用createElement方法。Element加入Element树中,都会调用mount方法。
- RanderElement继承RenderObjectElement继承Element
主要创建RenderObject对象,通过mount方法创建RenderObject对象。
-
StatefulElement继承ComponentElement
-
调用createState方法,创建state
- 将Widget赋值给State对象
-
调用state的build方法,并且将自己(Element)传出去
-
StatelessElement继承ComponentElement
主要调用build方法,并且将自己(Element)传出去