问题描述
StatefulWidget作为一种状态可变的控件,其状态的改变通常是由State.setState
进行的,但当我们需要在StatefulWidget之外改变它的状态时,因Widget的重新构造并不一定使得State重新构造,所以我们难以直接获取当前Widget所绑定的State,从而改变StatefulWidget的状态。
解决方案
常规方案
我们可以为StatefulWidget设置一个GlobalKey()
,通过GlobalKey.currentState
来获取当前绑定的State实例。示例如下:
class _Widget extends StatefulWidget {
final GlobalKey _key;
final double width;
final double height;
const _Widget(this.width, this.height, this._key) : super(key: _key);
@override
State<StatefulWidget> createState() => _State();
void setSize(double width, double height) {
var state = _key.currentState;
if (state is _State) {
state.setSize(width, height);
}
}
}
class _State extends State<_Widget> {
...
void setSize(double width, double height) {
setState(() {
_width = width;
_height = height;
});
}
...
}
此时就可以通过_Widget.setSize
来改变该StatefulWidget的状态。
另辟蹊径
只适用于只使用StatefulWidget的一个实例。
对于一个StatefulWidget,其Widget实例可以有多个,但其State实例只有一个。因此当只使用该StatefulWidget的一个实例时(即页面上只有一个该自定义的StatefulWidget控件),可以通过静态字段来引用State实例。示例如下:
class _Widget extends StatefulWidget {
final double width;
final double height;
const _Widget(this.width, this.height, {Key? key}) : super(key: key);
@override
State<StatefulWidget> createState() {
return _State();
}
void setSize(double width, double height) {
_State.state?.setSize(width, height);
}
}
class _State extends State<_Widget> {
static _State? state;
_State() {
state = this;
}
void setSize(double width, double height) {
setState(() {
_width = width;
_height = height;
});
}
@override
void dispose() {
super.dispose();
state = null;
}
...
}