- 优先选择StatelessWidget。
- 对于需要Widget自行维护状态,而这个状态又不需要暴露给父Widget的,使用StatefulWidget。其中状态定义在State中,而非StatefulWidget中。
- 父Widget传给子Widget数据,有两种情况:
- 父Widget同时传入数据更新函数。当子Widget操作数据更新时,调用此函数。父Widget必须是StatefulWidget。
- 子Widget自行维护数据的更新和显示。子Widget必须是StatefulWidget。
方式一: 父Widget负责数据更新维护
首先定义父Widget:
class ParentWidget extends StatefulWidget {
@override
_ParentWidgetState createState() => new _ParentWidgetState();
}
class _ParentWidgetState extends State<ParentWidget> {
bool _active = false;
void updateValue(bool newValue) {
setState(() {
_active = newValue;
});
}
@override
Widget build(BuildContext context) {
return ChildWidget(
active: _active,
parentUpdate: updateValue,
);
}
}
然后定义子Widget:
class ChildWidget extends StatefulWidget {
bool active;
Function parentUpdate;
ChildWidget({Key key, this.active: false, @required this.parentUpdate}) : super(key: key);
_ChildWidgetState createState() => new _ChildWidgetState();
}
class _ChildWidgetState extends State<ChildWidget> {
@override
Widget build(BuildContext context) {
return new Column(
children: [
Text(widget.active ? 'Active' : 'Inactive'),
RaisedButton(
child: Text('change active'),
onPressed: () {
widget.parentUpdate(!widget.active);
},
)
],
);
}
}
如上。父Widget将数据和更新函数同时传给了子Widget。子Widget的显示依赖于该数据。
当对子Widget进行操作,需要更改显示内容时,子Widget调用父Widget的更新函数即可。父Widget对数据更改并触发更新。子Widget判定可复用,然后用新的Widget数据更新自身。于是子Widget的显示得以更新。
方式二: 子Widget负责数据更新维护
首先定义父Widget:
class ParentWidget extends StatelessWidget {
ParentWidget({Key key}) : super(key: key);
final bool active;
@override
Widget build(BuildContext context) {
return ChildWidget(
active: active,
);
}
}
然后定义子Widget:
class ChildWidget extends StatefulWidget {
bool active;
ChildWidget({Key key, this.active: false}) : super(key: key);
_ChildWidgetState createState() => new _ChildWidgetState();
}
class _ChildWidgetState extends State<ChildWidget> {
@override
Widget build(BuildContext context) {
return new Column(
children: [
Text(widget.active ? 'Active' : 'Inactive'),
RaisedButton(
child: Text('change active'),
onPressed: () {
setState(() {
widget.active = !widget.active;
});
},
)
],
);
}
}
如上。父Widget将数据传给了子Widget。子Widget的显示依赖于该数据。
当对子Widget进行操作,需要更改显示内容时,子Widget调用自身的更新函数来修改数据值。
在此情形下,父Widget可以是StatelessWidget/StatefulWidget。
注意上面直接用widget.xx来使用/修改数据。对于父Widget传入的数据,推荐使用此方式,而不是在State中再次定义一个变量来再次接收。
StatefulWidget的维护方式选择
对于上面两种方式,对应不同的需求场景。通常来说:
- 若父Widget的数据影响到多个子Widget,即某个子Widget修改了数据后,多个子Widget都会同步更新,那么必须让父Widget来维护数据更新,也就是上面方式一。
- 若父Widget的数据只影响到单个子Widget,也就是说子Widget修改了数据后,只有自身会更新,那么推荐子Widget自行维护,也就是上面方式二。
对逻辑而言,两种方式都可以实现更改父Widget中数据的目的。区别在于更改数据后,谁负责将这个改动体现在界面上。
通常来说,2是最常见的。且2中父Widget可以是StatelessWidget/StatefulWidget。常规开发推荐使用2。
若不得不采用1,则父Widget必须是StatefulWidget,因为要提供修改函数。