ps: 文中flutter源码版本 1.0.0

widget基本分为StatelessWidget、StatefulWidget、RenderObjectWidget和ProxyWidget 4类型(子类PreferredSizeWidget是一个接口)
先从最简单的开始分析:
StatelessWidget
1. 这是什么?
StatelessWidget是一个无状态的控件,之前我们只关心其的build方法,那么其的build是什么时候调用的呢?
abstract class StatelessWidget extends Widget {
const StatelessWidget({ Key key }) : super(key: key);
@override
StatelessElement createElement() => StatelessElement(this);
@protected
Widget build(BuildContext context);
}
class StatelessElement extends ComponentElement {
StatelessElement(StatelessWidget widget) : super(widget);
//这种写法在flutter中比较常见
//widget就是StatelessWidget的createElement()方法中传递的this
@override
StatelessWidget get widget => super.widget;
//调用StatelessWidget中的build
@override
Widget build() => widget.build(this);
@override
void update(StatelessWidget newWidget) {
super.update(newWidget);
assert(widget == newWidget);
_dirty = true;
rebuild();
}
}
这个问题就转换为什么时候调用StatelessElement中的build方法
带着这个问题,我们从头开始捋
2. 定义一个起点
flutter的main函数初始都是这么写的,ok,我们就按这个顺序分析下来
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp();
}
}
后续过程中很多源码其实之前已经分析过,这里还是过一下。先看runApp方法:
void runApp(Widget app) {
WidgetsFlutterBinding.ensureInitialized()
..attachRootWidget(app)
..scheduleWarmUpFrame();
}
我们只关心直接的MyAPP控件是什么时候build的,所以直接看attachRootWidget(app)
void attachRootWidget(Widget rootWidget) {
_renderViewElement = RenderObjectToWidgetAdapter<RenderBox>(
container: renderView,
debugShortDescription: '[root]',
child: rootWidget
).attachToRenderTree(buildOwner, renderViewElement);
}
创建了一个RenderObjectToWidgetAdapter控件,并调用了attachToRenderTree方法
class RenderObjectToWidgetAdapter<T extends RenderObject> extends RenderObjectWidget {
RenderObjectToWidgetAdapter({
this.child,
this.container,
this.debugShortDescription
}) : super(key: GlobalObjectKey(container));
final String debugShortDescription;
@override
RenderObjectToWidgetElement<T> createElement() => RenderObjectToWidgetElement<T>(this);
@override
RenderObjectWithChildMixin<T> createRenderObject(BuildContext context) => container;
@override
void updateRenderObject(BuildContext context, RenderObject renderObject) { }
RenderObjectToWidgetElement<T> attachToRenderTree(BuildOwner owner, [RenderObjectToWidgetElement<T> element]) {
//不存在则创建一个
if (element == null) {
owner.lockState(() {
//创建了一个RenderObjectToWidgetElement
element = createElement();
assert(element != null);
element.assignOwner(owner);
});
owner.buildScope(element, () {
//进行登记
element.mount(null, null);
});
} else {
element._newWidget = this;
element.markNeedsBuild();
}
return element;
}
来到RenderObjectToWidgetElement中的mount方法
@override
void mount(Element parent, dynamic newSlot) {
assert(parent == null);
super.mount(parent, newSlot);
_rebuild();
}
void _rebuild() {
try {
//这里传递的是widget.child,widget就是RenderObjectToWidgetAdapter
//child即是MyApp控件
//参数_child为未更新前的child,初始为null
_child = updateChild(_child, widget.child, _rootChildSlot);
assert(_child != null);
} catch (exception, stack) {
...
);
...
}
}
updateChild在基础父类Element中
@protected
Element updateChild(Element child, Widget newWidget, dynamic newSlot) {
...
//本次的child是未null的,只要再次调用rebuild才有值
if (newWidget == null) {
if (child != null)
deactivateChild(child);
return null;
}
if (child != null) {
if (child.widget == newWidget) {
if (child.slot != newSlot)
updateSlotForChild(child, newSlot);
return child;
}
//条件,必须新旧控件相同
if (Widget.canUpdate(child.widget, newWidget)) {
if (child.slot != newSlot)
updateSlotForChild(child, newSlot);
//执行这一步的条件必须是child有值,但第一次调用build方法时,child为null,只有第二次后才有值
//这里会调用Element中的update方法
child.update(newWidget);
...
return child;
}
deactivateChild(child);
assert(child._parent == null);
}
return inflateWidget(newWidget, newSlot);
}
//类型和key相同则表示同一个控件
static bool canUpdate(Widget oldWidget, Widget newWidget) {
return oldWidget.runtimeType == newWidget.runtimeType
&& oldWidget.key == newWidget.key;
}
渲染控件,并且向下遍历
@protected
Element inflateWidget(Widget newWidget, dynamic newSlot) {
//省略断言判断
...
//newWidget即是MyApp,是一个StatelessWidget,所以创建了一个StatelessElement
final Element newChild = newWidget.createElement();
assert(() { _debugCheckForCycles(newChild); return true; }());
//StatelessElement中的mount
newChild.mount(this, newSlot);
assert(newChild._debugLifecycleState == _ElementLifecycle.active);
return newChild;
}
StatelessElement中无mount方法,在其父类ComponentElement找到
@override
void mount(Element parent, dynamic newSlot) {
super.mount(parent, newSlot);
assert(_child == null);
assert(_active);
_firstBuild();
assert(_child != null);
}
void _firstBuild() {
rebuild();
}
ComponentElement无rebuild,寻找其父类Element中方法
void rebuild() {
//省略断言判断
...
performRebuild();
...
}
再回到ComponentElement,找到其performRebuild(),此时就很明朗了
@override
void performRebuild() {
//省略了断言和错误处理
...
Widget built;
try {
//调用StatelessElement中的build()方法
built = build();
debugWidgetBuilderValue(widget, built);
} catch (e, stack) {
...
} finally {
...
}
try {
//遍历下去
_child = updateChild(_child, built, slot);
assert(_child != null);
} catch (e, stack) {
...
}
...
}
至此,build的流程就结束了
StatefulWidget
1. 这是什么?
StatefulWidget是一个有状态的控件,build调用的流程和上面是一样的,先StatefulElement的build方法,然后调用state中的build方法
abstract class StatefulWidget extends Widget {
const StatefulWidget({ Key key }) : super(key: key);
@override
StatefulElement createElement() => StatefulElement(this);
@protected
State createState();
}
2. state生命周期

其实也就是widget的element的创建、改变和消除的生命周期
我们按照这个图过一下state的生命周期的源码执行顺序:
class StatefulElement extends ComponentElement {
StatefulElement(StatefulWidget widget)
// --- 1. 构造函数创建state
: _state = widget.createState(), super(widget) {
//省略了断言判断
...
_state._element = this;
_state._widget = widget;
}
// --- 4. 调用build()方法,显示在树上
@override
Widget build() => state.build(this);
State<StatefulWidget> get state => _state;
State<StatefulWidget> _state;
@override
void _reassemble() {
state.reassemble();
super._reassemble();
}
@override
void _firstBuild() {
...
try {
_debugSetAllowIgnoredCallsToMarkNeedsBuild(true);
// --- 2. 调用initState()
final dynamic debugCheckForReturnedFuture = _state.initState() as dynamic;
...
} finally {
_debugSetAllowIgnoredCallsToMarkNeedsBuild(false);
}
...
// --- 3. 调用didChangeDependencies()
_state.didChangeDependencies();
...
super._firstBuild();
}
// --- 5. 控件第二次调用自己的build方法时调用,即外部使用setState,重新绘制子树
@override
void update(StatefulWidget newWidget) {
super.update(newWidget);
final StatefulWidget oldWidget = _state._widget;
_dirty = true;
_state._widget = widget;
try {
_debugSetAllowIgnoredCallsToMarkNeedsBuild(true);
// --- 6. 调用didUpdateWidget()
final dynamic debugCheckForReturnedFuture = _state.didUpdateWidget(oldWidget) as dynamic;
...
} finally {
_debugSetAllowIgnoredCallsToMarkNeedsBuild(false);
}
// --- 7. 执行build
rebuild();
}
//build组件时调用,代表组件是活跃状态
@override
void activate() {
super.activate();
assert(_active);
markNeedsBuild();
}
//build控件时调用,代表组件是非活跃状态
@override
void deactivate() {
_state.deactivate();
super.deactivate();
}
//drawFrame时清空空闲控件时,若空闲则调用,解除登记
@override
void unmount() {
super.unmount();
_state.dispose();
...
_state._element = null;
_state = null;
}
@override
InheritedWidget inheritFromElement(Element ancestor, { Object aspect }) {
...
return super.inheritFromElement(ancestor, aspect: aspect);
}
@override
void didChangeDependencies() {
super.didChangeDependencies();
_state.didChangeDependencies();
}
@override
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
super.debugFillProperties(properties);
properties.add(DiagnosticsProperty<State<StatefulWidget>>('state', state, defaultValue: null));
}
}
3. setState 更新状态
state进行更新,执行setState方法,这个之前分析过,这里贴个图:

@protected
void setState(VoidCallback fn) {
//去除断言
...
final dynamic result = fn() as dynamic;
_element.markNeedsBuild();
}
void markNeedsBuild() {
...
if (dirty)
return;
_dirty = true;
owner.scheduleBuildFor(this);
}
//对修改的脏数据进行标记和添加到列表中
void scheduleBuildFor(Element element) {
...
if (!_scheduledFlushDirtyElements && onBuildScheduled != null) {
_scheduledFlushDirtyElements = true;
onBuildScheduled();
}
//添加_dirtyElements列表中
_dirtyElements.add(element);
//标记
element._inDirtyList = true;
...
}
最后会通过c/c++回调drawFrame方法
@override
void drawFrame() {
...
try {
if (renderViewElement != null)
//执行rebuild,再次调用StatefulWidget的build方法
buildOwner.buildScope(renderViewElement);
//绘制
super.drawFrame();
//释放空闲,解除登记
buildOwner.finalizeTree();
} finally {
...
}
...
}
执行rebuild方法
void buildScope(Element context, [VoidCallback callback]) {
if (callback == null && _dirtyElements.isEmpty)
return;
...
Timeline.startSync('Build', arguments: timelineWhitelistArguments);
try {
_scheduledFlushDirtyElements = true;
if (callback != null) {
assert(_debugStateLocked);
Element debugPreviousBuildTarget;
...
_dirtyElementsNeedsResorting = false;
try {
callback();
} finally {
...
}
}
_dirtyElements.sort(Element._sort);
_dirtyElementsNeedsResorting = false;
int dirtyCount = _dirtyElements.length;
int index = 0;
while (index < dirtyCount) {
...
try {
//执行
_dirtyElements[index].rebuild();
} catch (e, stack) {
...
}
index += 1;
if (dirtyCount < _dirtyElements.length || _dirtyElementsNeedsResorting) {
_dirtyElements.sort(Element._sort);
_dirtyElementsNeedsResorting = false;
dirtyCount = _dirtyElements.length;
while (index > 0 && _dirtyElements[index - 1].dirty) {
index -= 1;
}
}
}
...
} finally {
for (Element element in _dirtyElements) {
assert(element._inDirtyList);
element._inDirtyList = false;
}
_dirtyElements.clear();
_scheduledFlushDirtyElements = false;
_dirtyElementsNeedsResorting = null;
Timeline.finishSync();
...
}
...
}
RenderObjectWidget
1.这是什么?
abstract class RenderObjectWidget extends Widget {
const RenderObjectWidget({ Key key }) : super(key: key);
@override
RenderObjectElement createElement();
@protected
RenderObject createRenderObject(BuildContext context);
@protected
void updateRenderObject(BuildContext context, covariant RenderObject renderObject) { }
@protected
void didUnmountRenderObject(covariant RenderObject renderObject) { }
}
除了继承来的createElement()方法,还新增了3个方法,这次主要研究这三个方法调用的时机
RenderObjectWidget是一个抽象类,createElement()并未像之前一样实现了,但是没关系,我们可以看到其的返回类型是RenderObjectElement,这是返回通用的父类
abstract class RenderObjectElement extends Element {
RenderObjectElement(RenderObjectWidget widget) : super(widget);
@override
RenderObjectWidget get widget => super.widget;
@override
RenderObject get renderObject => _renderObject;
RenderObject _renderObject;
...
@override
void mount(Element parent, dynamic newSlot) {
super.mount(parent, newSlot);
// -- 1.
_renderObject = widget.createRenderObject(this);
assert(() { _debugUpdateRenderObjectOwner(); return true; }());
assert(_slot == newSlot);
attachRenderObject(newSlot);
_dirty = false;
}
@override
void update(covariant RenderObjectWidget newWidget) {
super.update(newWidget);
assert(widget == newWidget);
assert(() { _debugUpdateRenderObjectOwner(); return true; }());
// -- 2.
widget.updateRenderObject(this, renderObject);
_dirty = false;
}
@override
void performRebuild() {
// -- 2.
widget.updateRenderObject(this, renderObject);
_dirty = false;
}
...
@override
void unmount() {
super.unmount();
//省略断言
...
// -- 3.
widget.didUnmountRenderObject(renderObject);
}
...
}
经过前面的分析 ,其实本身比较简单,复杂的部分都在RenderObject上,如何摆放和绘制
针对ProxyWidget放在下一篇:深入分析Widget 2
网友评论