Widget

Widget是我们在Flutter中接触到的最多的类。

从逻辑上来说,Widget的关系图可以分为以下几个部分。(当然Flutter中并没有组合型组件这么一个Class)

Widget关系图

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
///Describes the configuration for an [Element].
///描述 [Element] 的配置文件
@immutable
abstract class Widget extends DiagnosticableTree {
const Widget({ this.key });
final Key? key;
...
@protected
Element createElement();
...

static bool canUpdate(Widget oldWidget, Widget newWidget) {
return oldWidget.runtimeType == newWidget.runtimeType
&& oldWidget.key == newWidget.key;
}
}

Widget的源码非常简单,这里把主要的贴出来。可以看到Widget类中主要的东西有

1.构造方法中入参key

2.静态的canUpdate方法

3.抽象方法createElement()

而在Widget的子类中,都各自对createElement()进行了具体的实现

组合型Widget

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

abstract class StatelessWidget extends Widget {
...
@override
StatelessElement createElement() => StatelessElement(this);
...

@protected
Widget build(BuildContext context);
}

abstract class StatefulWidget extends Widget {
...
@override
StatefulElement createElement() => StatefulElement(this);
...

@protected
@factory
State createState();
}

abstract class ProxyWidget extends Widget {

const ProxyWidget({ Key? key, required this.child }) : super(key: key);

final Widget child;
}

abstract class InheritedWidget extends ProxyWidget {
...
@override
InheritedElement createElement() => InheritedElement(this);
...
}

abstract class ParentDataWidget<T extends ParentData>extends ProxyWidget{

@override
ParentDataElement<T>createElement()=> ParentDataElement<T>(this);

@protected
void applyParentData(RenderObject renderObject);
}
1
2
StatelessElement,StatefulElement,
InheritedElement,ParentDataElement,都是ComponentElement的子类

可以看到组合类型的Widget的createElement()方法创建了不同类型的ComponentElement

渲染型Widget

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
RenderObjectWidget系列的createElement()方法都是创建了RenderObjectElement

abstract class RenderObjectWidget extends Widget {

/// RenderObjectWidgets always inflate to a [RenderObjectElement] subclass.
@override
@factory
RenderObjectElement createElement();

///创建渲染对象
@protected
@factory
RenderObject createRenderObject(BuildContext context);

///更新渲染对象
@protected
void updateRenderObject(BuildContext context, covariant RenderObject renderObject) { }

@protected
void didUnmountRenderObject(covariant RenderObject renderObject) { }

}

///叶子节点的RenderObjectWidget
abstract class LeafRenderObjectWidget extends RenderObjectWidget {

@override
LeafRenderObjectElement createElement() => LeafRenderObjectElement(this);
}

///单子节点的RenderObjectWidget
abstract class SingleChildRenderObjectWidget extends RenderObjectWidget {
final Widget? child;

@override
SingleChildRenderObjectElement createElement() => SingleChildRenderObjectElement(this);
}

///多子节点的RenderObjectWidget
abstract class MultiChildRenderObjectWidget extends RenderObjectWidget {

final List<Widget> children;

@override
MultiChildRenderObjectElement createElement() => MultiChildRenderObjectElement(this);
}
1
2
LeafRenderObjectElement,SingleChildRenderObjectElement,
MultiChildRenderObjectElement都是RenderObjectElement的子类。

RenderObjectWidget的createElement方法创建了不同类型的RenderObjectElement。RenderObjectWidget提供createRenderObject方法创建RenderObject。

总结

Widget是描述 [Element] 的配置文件,主要功能就是createElement(),该方法都是返回了xxxElement(this),可以看到创建Element的入参是Widget。

RenderObjectWidget还提供createRenderObject(BuildContext context)方法创建RenderObject。

单独看Widget的源码其实没什么意义,需要结合Element的源码才行。