Flutter源码分析

关联项目: https://github.com/ixyxj/flutter_cookbook

控件Widget

Flutter UI的创建都是继承自Widget

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/// 一个元素配置的描述, 所有的控件都是继承自此类, 其中包括两个抽象类,分别是无状态和有状态
///
/// 其中比较关键的是Key和runtimeType, 如果两个控件的这两个值相等, 就会在渲染树种被另一个控件替换掉
@immutable
abstract class Widget extends DiagnosticableTree {
const Widget({ this.key });
final Key key;

/// 创建一个元素实例
@protected
Element createElement();

...

/// 这里就是key的作用了.
static bool canUpdate(Widget oldWidget, Widget newWidget) {
return oldWidget.runtimeType == newWidget.runtimeType
&& oldWidget.key == newWidget.key;
}
}

从上面可以看到关键的部分就是createElement(), 找到两个实现类,是三个^_^.

  • StatelessWidget
1
2
3
4
5
6
7
8
9
abstract class StatelessWidget extends Widget {
...
//创建无状态的元素
@override
StatelessElement createElement() => StatelessElement(this);
...
@protected
Widget build(BuildContext context);
}

创建无状态元素:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/// An [Element] that uses a [StatelessWidget] as its configuration.
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;

//这里的build就是子类需要实现的
@override
Widget build() => widget.build(this);

//控件是否改变.
@override
void update(StatelessWidget newWidget) {
super.update(newWidget);
assert(widget == newWidget);
_dirty = true;
rebuild();
}
}
  • StatefulWidget

分析了无状态, 有状态的控件同理,但复杂一些

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
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
/// An [Element] that uses a [StatefulWidget] as its configuration.
class StatefulElement extends ComponentElement {
/// Creates an element that uses the given widget as its configuration.
StatefulElement(StatefulWidget widget)
: _state = widget.createState(), super(widget) {
assert(() {
/// 判断类型, 类型不对抛出错误, returned a state
if (!_state._debugTypesAreRight(widget)) {
throw FlutterError(
'StatefulWidget.createState must return a subtype of State<${widget.runtimeType}>\n'
'The createState function for ${widget.runtimeType} returned a state '
'of type ${_state.runtimeType}, which is not a subtype of '
'State<${widget.runtimeType}>, violating the contract for createState.'
);
}
return true;
}());
/// 将state赋值
assert(_state._element == null);
_state._element = this;
assert(_state._widget == null);
_state._widget = widget;
assert(_state._debugLifecycleState == _StateLifecycle.created);
}

@override
Widget build() => state.build(this);

/// 返回状态
State<StatefulWidget> get state => _state;
State<StatefulWidget> _state;

@override
void _reassemble() {
state.reassemble();
super._reassemble();
}

@override
void _firstBuild() {
assert(_state._debugLifecycleState == _StateLifecycle.created);
try {
_debugSetAllowIgnoredCallsToMarkNeedsBuild(true);
final dynamic debugCheckForReturnedFuture = _state.initState() as dynamic;
assert(() {
if (debugCheckForReturnedFuture is Future) {
throw FlutterError(
'${_state.runtimeType}.initState() returned a Future.\n'
'State.initState() must be a void method without an `async` keyword.\n'
'Rather than awaiting on asynchronous work directly inside of initState,\n'
'call a separate method to do this work without awaiting it.'
);
}
return true;
}());
} finally {
_debugSetAllowIgnoredCallsToMarkNeedsBuild(false);
}
assert(() { _state._debugLifecycleState = _StateLifecycle.initialized; return true; }());
_state.didChangeDependencies();
assert(() { _state._debugLifecycleState = _StateLifecycle.ready; return true; }());
super._firstBuild();
}

@override
void update(StatefulWidget newWidget) {
super.update(newWidget);
assert(widget == newWidget);
final StatefulWidget oldWidget = _state._widget;
// Notice that we mark ourselves as dirty before calling didUpdateWidget to
// let authors call setState from within didUpdateWidget without triggering
// asserts.
_dirty = true;
_state._widget = widget;
try {
_debugSetAllowIgnoredCallsToMarkNeedsBuild(true);
final dynamic debugCheckForReturnedFuture = _state.didUpdateWidget(oldWidget) as dynamic;
assert(() {
if (debugCheckForReturnedFuture is Future) {
throw FlutterError(
'${_state.runtimeType}.didUpdateWidget() returned a Future.\n'
'State.didUpdateWidget() must be a void method without an `async` keyword.\n'
'Rather than awaiting on asynchronous work directly inside of didUpdateWidget,\n'
'call a separate method to do this work without awaiting it.'
);
}
return true;
}());
} finally {
_debugSetAllowIgnoredCallsToMarkNeedsBuild(false);
}
rebuild();
}

/// 激活和失效回收资源
@override
void activate() {
super.activate();
assert(_active); // otherwise markNeedsBuild is a no-op
markNeedsBuild();
}

@override
void deactivate() {
_state.deactivate();
super.deactivate();
}

@override
void unmount() {
super.unmount();
_state.dispose();
assert(() {
if (_state._debugLifecycleState == _StateLifecycle.defunct)
return true;
throw FlutterError(
'${_state.runtimeType}.dispose failed to call super.dispose.\n'
'dispose() implementations must always call their superclass dispose() method, to ensure '
'that all the resources used by the widget are fully released.'
);
}());
_state._element = null;
_state = null;
}

@override
InheritedWidget inheritFromElement(Element ancestor, { Object aspect }) {
assert(ancestor != null);
assert(() {
final Type targetType = ancestor.widget.runtimeType;
if (state._debugLifecycleState == _StateLifecycle.created) {
throw FlutterError(
'inheritFromWidgetOfExactType($targetType) or inheritFromElement() was called before ${_state.runtimeType}.initState() completed.\n'
'When an inherited widget changes, for example if the value of Theme.of() changes, '
'its dependent widgets are rebuilt. If the dependent widget\'s reference to '
'the inherited widget is in a constructor or an initState() method, '
'then the rebuilt dependent widget will not reflect the changes in the '
'inherited widget.\n'
'Typically references to to inherited widgets should occur in widget build() methods. Alternatively, '
'initialization based on inherited widgets can be placed in the didChangeDependencies method, which '
'is called after initState and whenever the dependencies change thereafter.'
);
}
if (state._debugLifecycleState == _StateLifecycle.defunct) {
throw FlutterError(
'inheritFromWidgetOfExactType($targetType) or inheritFromElement() was called after dispose(): $this\n'
'This error happens if you call inheritFromWidgetOfExactType() on the '
'BuildContext for a widget that no longer appears in the widget tree '
'(e.g., whose parent widget no longer includes the widget in its '
'build). This error can occur when code calls '
'inheritFromWidgetOfExactType() from a timer or an animation callback. '
'The preferred solution is to cancel the timer or stop listening to the '
'animation in the dispose() callback. Another solution is to check the '
'"mounted" property of this object before calling '
'inheritFromWidgetOfExactType() to ensure the object is still in the '
'tree.\n'
'This error might indicate a memory leak if '
'inheritFromWidgetOfExactType() is being called because another object '
'is retaining a reference to this State object after it has been '
'removed from the tree. To avoid memory leaks, consider breaking the '
'reference to this object during dispose().'
);
}
return true;
}());
return super.inheritFromElement(ancestor, aspect: aspect);
}

@override
void didChangeDependencies() {
super.didChangeDependencies();
_state.didChangeDependencies();
}
...
}
  • InheritedWidget, 此类继承与ProxyWidget, 而ProxyWidget继承与Widget并传入child
1
2
3
4
5
6
7
8
9
abstract class ProxyWidget extends Widget {
/// Creates a widget that has exactly one child widget.
const ProxyWidget({ Key key, @required this.child }) : super(key: key);

/// The widget below this widget in the tree.
///
/// {@macro flutter.widgets.child}
final Widget child;
}

首先分析最简单的Text控件

日志

Trees of Flutter diagnostics:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 显示等级, 一般都在debug以上
enum DiagnosticLevel {
/// 不显示
hidden,
/// 显示默认值,不加新值
fine,
/// 对比fine, 一些重要的对象需要这个模式
debug,
/// 有目的的显示信息
info,
/// 一些重要可能有问题的值
warning,
/// 错误显示
error,
/// 特别, 没有诊断被显示
off,
}
Donate comment here