简介
Flutter作为跨平台的语言越来越被重视,特别是近两年许多互联网公司都在降本增效的时候,学会Flutter开发就变得十分重要了,有助于在日常工作中不被淘汰。
在Java中,万事万物皆为对象。同样在Flutter中,几乎所有的对象都是一个Widget。和其他开发语言不同的是,Flutter中的widget表示的含义更广泛,UI元素,View组件,主题,手势事件等都是一个Widget。
分类
Flutter中的Widget主要分为两类StatelessWidget和StatefulWidget。
- StatelessWidget表示无状态的Widget。
- StatefulWidget表示有状态的Widget。
区别
下面分别从代码结构,使用场景来区分两种Widget的不同.
代码结构
- StatelessWidget
从源码可以看出StatelessWidget是一个抽象类继承自Widget,内部默认实现创建了一个StatelessElement 对象和build方法。StatelessElement内部也只有一个update方法用来构建页面。
- StatefulWidget
abstract class StatefulWidget extends Widget {
/// Initializes [key] for subclasses.
const StatefulWidget({ super.key });
@override
StatefulElement createElement() => StatefulElement(this);
/// [State] objects.
@protected
@factory
State createState();
}
class StatefulElement extends ComponentElement {
.................
@override
Widget build() => state.build(this);
State<StatefulWidget> get state => _state!;
State<StatefulWidget>? _state;
...............
@override
void update(StatefulWidget newWidget) {
super.update(newWidget);
assert(widget == newWidget);
final StatefulWidget oldWidget = state._widget!;
state._widget = widget as StatefulWidget;
..............
return true;
}());
rebuild(force: true);
}
@override
void activate() {
super.activate();
state.activate();
assert(_lifecycleState == _ElementLifecycle.active); // otherwise markNeedsBuild is a no-op
markNeedsBuild();
}
@override
void deactivate() {
state.deactivate();
super.deactivate();
}
@override
void unmount() {
super.unmount();
state.dispose();
state._element = null;
_state = null;
}
@override
InheritedWidget dependOnInheritedElement(Element ancestor, { Object? aspect }) {
assert(ancestor != null);
.....
return super.dependOnInheritedElement(ancestor as InheritedElement, aspect: aspect);
}
bool _didChangeDependencies = false;
@override
void didChangeDependencies() {
super.didChangeDependencies();
_didChangeDependencies = true;
}
@override
DiagnosticsNode toDiagnosticsNode({ String? name, DiagnosticsTreeStyle? style }) {
return _ElementDiagnosticableTreeNode(
name: name,
value: this,
style: style,
stateful: true,
);
}
@override
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
super.debugFillProperties(properties);
properties.add(DiagnosticsProperty<State<StatefulWidget>>('state', _state, defaultValue: null));
}
}
StatefulWidget内部StatefulElement 中不仅有update()方法还有activate,deactivate,didChangeDependencies等方法。具体方法使用以后慢慢讲解。
使用场景
1 StatelessWidget
StatelessWidget从字面意思就可以看出是无状态的Widget。这里的无状态通俗来说,一旦控件确定,就不能改变其状态。包括显示状态,点击状态等。通常用来表示一些不涉及到页面变化,更新等控件。
示例:
这里封装了一个CommonButton按钮,按钮的构造函数中只传入了text文本和点击事件的回调。也就是说一旦传入了text,按钮本身的显示状态并不会发生改变,而且点击事件也是由调用者来实现,对应按钮本身来说不会发生任何改变。
2 StatefulWidget
StatefulWidget表示有状态的widget,或者是说有生命周期的Widget,这里的状态同样是指widget本身的状态,如形状,角度,颜色,背景色等发生改变。
示例:
同样还是CommonButton,这次继承自StatefulWidget,给按钮添加了一个旋转动画,在initState方法中初始化动画控制器,在dispose方法中解绑控制器,由于是给按钮本身添加了动画,当点击按钮时,按钮自身状态发生了改变。所以必须要用StatefulWidget,如果用StatelessWidget是无法实现按钮自身的旋转的。读者可以动手试试。
总结
在Flutter中,不论是StatelessWidget还是StatefulWidget都是经常使用的控件,熟练掌握Widget的基本使用场景有效提高开发效率,特别是正确区分不同Widget的使用场景,本文从简单的Widget开始介绍StatelessWidget和StatefulWidget和区别和使用场景。
后续会使用Flutter语言仿一个抖音的项目。感兴趣的同学可以点击关注哦!