最近几天有一搭没一搭的学习 Flutter,在 Flutter 中一切皆 Widget ,那么组件是不是单单指UI元素呢?比如文本框、按钮、弹窗等等一系列 UI 控件,想必很多新入手 Flutter 的朋友都会心存疑惑。答案是否定的。
在 Flutter中,控件是Element,Widget 更多的指的是UI元素的一个配置数据,并且一个Widget可以对应多个UI元素,比如手势检测的 GestureDetector widget。编码中最多使用的抽象类就是无状态组件 StatelessWidget 和 有状态组件StatefulWidget ,而这两个类都继承Widget,接下来看看这三个类的源码吧。
widget组件源码分析
//该类是一个抽象类,继承DiagnosticableTree(诊断树,主要作用是提供调试信息)
@immutable
abstract class Widget extends DiagnosticableTree {
// 在之类中初始化key
const Widget({ this.key });
// 组件唯一标识,判断时使用,决定是否在下一次build时复用旧的widget,决定条件在canUpdate()方法中
final Key? key;
// 创建一个Element对象,子类需重写该方法
@protected
@factory
Element createElement();
//查看组件的运行类型及唯一标识
@override
String toStringShort() {
final String type = objectRuntimeType(this, 'Widget');
return key == null ? type : '$type-$key';
}
//重写父类的方法,主要设置诊断树的一些特性
@override
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
super.debugFillProperties(properties);
properties.defaultDiagnosticsTreeStyle = DiagnosticsTreeStyle.dense;
}
//重写父类的方法
@override
@nonVirtual
bool operator ==(Object other) => super == other;
//重写父类的方法,获取父类的hashCode
@override
@nonVirtual
int get hashCode => super.hashCode;
// 组件是否被更改的判断
static bool canUpdate(Widget oldWidget, Widget newWidget) {
return oldWidget.runtimeType == newWidget.runtimeType
&& oldWidget.key == newWidget.key;
}
// 获取组件类型,是无状态的组件,还是有状态的组件,还是其他
static int _debugConcreteSubtype(Widget widget) {
return widget is StatefulWidget ? 1 :
widget is StatelessWidget ? 2 :
0;
}
}
Widget 又分为无状态的 StatelessWidget 和有状态的StatefullWidget 两大类,这两个类都继承了Widget。
StatelessWidget 源码分析
/// StatelessWidget是一个抽象类,继承Widget,用于不需要维护状态的场景
abstract class StatelessWidget extends Widget {
/// 帮助子类初始化key
const StatelessWidget({ Key? key }) : super(key: key);
/// 创建一个无状态的组件,并在本地管理这个组件,无需子类重写
/// StatelessElement 与 StatelessWidget 相对应
@override
StatelessElement createElement() => StatelessElement(this);
/// 子类需要重写的方法,构建无状态组件
@protected
Widget build(BuildContext context);
}
StatefulWidget 源码分析
/// StatelessWidget是一个抽象类,继承Widget,用于需要维护状态的场景
abstract class StatefulWidget extends Widget {
/// 帮助子类初始化key
const StatefulWidget({ Key? key }) : super(key: key);
/// 创建一个有状态的组件,并在本地管理这个组件,无需子类重写
/// StatefulElement 与 StatefulWidget相对应
@override
StatefulElement createElement() => StatefulElement(this);
/// 状态管理,需要子类重写
@protected
@factory
State createState();
}
那么,State又是个啥玩意呢?一个StatefulWidget类会对应一个State类,State表示与其对应的StatefulWidget要维护的状态。
State源码分析
/// State也是一个抽象类,与StatefulWidget类一一对应
@optionalTypeArgs
abstract class State<T extends StatefulWidget> with Diagnosticable {
T get widget => _widget!;
T? _widget;
/// _StateLifecycle生命周期包括:created[State.initState]、initialized[State.didChangeDependencies]、ready、defunct[State.dispose]
_StateLifecycle _debugLifecycleState = _StateLifecycle.created;
bool _debugTypesAreRight(Widget widget) => widget is T;
// 上下文获取,通过context可以从上下文获取其他组件,context.findAncestorWidgetOfExactType<Scaffold>()
BuildContext get context {
assert(() {
if (_element == null) {
/// 省略部分
}
return true;
}());
return _element!;
}
StatefulElement? _element;
bool get mounted => _element != null;
// 初始化状态,组件的生命周期开始,如果子类重写该方法必须调用父类即:super.initState();
@protected
@mustCallSuper
void initState() {
assert(_debugLifecycleState == _StateLifecycle.created);
}
/// 变更组件状态
@mustCallSuper
@protected
void didUpdateWidget(covariant T oldWidget) { }
/// 重写组装组件
@protected
@mustCallSuper
void reassemble() { }
/// 设置组件状态,将需要保持的状态放置到该方法中
@protected
void setState(VoidCallback fn) {
assert(fn != null);
assert(() {
if (_debugLifecycleState == _StateLifecycle.defunct) {
/// 省略部分
}
if (_debugLifecycleState == _StateLifecycle.created && !mounted) {
/// 省略部分
}
return true;
}());
final Object? result = fn() as dynamic;
assert(() {
if (result is Future) {
/// 省略部分
}
return true;
}());
_element!.markNeedsBuild();
}
// 使状态无效
@protected
@mustCallSuper
void deactivate() { }
// 销毁组件
@protected
@mustCallSuper
void dispose() {
assert(_debugLifecycleState == _StateLifecycle.ready);
assert(() {
_debugLifecycleState = _StateLifecycle.defunct;
return true;
}());
}
如果没有实际的编码经验,看源码,只能对组件的状态管理有个粗略的理解,到底怎么使用,还需要练起来感觉一下的。
网友评论