我很难理解为什么有状态小部件在重建后没有更新状态。我有一个有状态的小部件,负责每秒减少一个计数器,因此它接收到一个初始值,我将此初始值传递给State并开始递减它。
还有一个按钮,当按下该按钮时,会将事件发送到我的集团,该集团使用新的初始值重建有状态的小部件,事实是,它确实发送并更新了初始值,但是计数器继续递减旧值,而我不知道为什么。这是代码示例:
小部件
void main() => runApp(
BlocProvider(
create: (context) => TBloc(),
child: MaterialApp(
home: Scaffold(
body: BlocBuilder<TBloc, BState>(
builder: (context, state) {
if (state is BState) {
return Column(
children: [
Counter(state.value),
FlatButton(
child: Text("tap"),
onPressed: () =>
BlocProvider.of<TBloc>(context).add(BEvent(200)),
),
],
);
}
return Container();
},
),
),
),
),
);
class Counter extends StatefulWidget {
final int initialValue;
Counter(this.initialValue);
@override
CounterState createState() => CounterState(this.initialValue);
}
class CounterState extends State<Counter> {
Timer timer;
int value;
CounterState(this.value);
@override
void initState() {
super.initState();
timer = Timer.periodic(Duration(seconds: 1), (timer) {
setState(() => --value);
});
}
@override
Widget build(BuildContext context) {
return Column(
mainAxisSize: MainAxisSize.min,
children: [
Text("Value: $value"),
Text("Initial: ${widget.initialValue}")
],
);
}
}
集团
class TBloc extends Bloc<BEvent, BState> {
@override
BState get initialState => BState(100);
@override
Stream<BState> mapEventToState(BEvent event) async* {
yield BState(event.value);
}
}
class BEvent extends Equatable {
final int value;
BEvent(this.value);
@override
List<Object> get props => [value];
}
class BState extends Equatable {
final int value;
BState(this.value);
@override
List<Object> get props => [value];
}
谢谢你。
这是因为您只在Timer
的Counter
上设置了initState
,每个小部件生命周期一次将其称为only。
[基本上,当您首次构建Counter
时,它将调用initState()
,并且只要它保留在该小部件树中,就只调用didUpdateWidget()
和/或didChangeDependencies()
来更新 小部件(例如,当您使用新参数重建时,就像在做的那样)。
dispose()
方法也是如此,这与initState()
仅称为once相反,但是这次是从树中删除窗口小部件。
此外,您在这里使用错误的状态。您不需要将参数传递给状态本身(就像您这样做的那样:
CounterState createState() => CounterState(this.initialValue);
但是,您可以通过调用:widget.initialValue
从该小部件访问all参数。
因此,基本上,您要做的就是基于新更新来更新Counter
小部件,如下所示:
class Counter extends StatefulWidget {
final int initialValue;
Counter(this.initialValue);
@override
CounterState createState() => CounterState();
}
class CounterState extends State<Counter> {
Timer timer;
int value;
void _setTimer() {
value = widget.initialValue;
timer = Timer.periodic(Duration(seconds: 1), (timer) {
setState(() => --value);
});
}
@override
void initState() {
super.initState();
_setTimer();
}
@override
void didUpdateWidget(Counter oldWidget) {
super.didUpdateWidget(oldWidget);
if(oldWidget.initialValue != widget.initialValue) {
_setTimer();
}
}
@override
Widget build(BuildContext context) {
return Column(
mainAxisSize: MainAxisSize.min,
children: [
Text("Value: $value"),
Text("Initial: ${widget.initialValue}")
],
);
}
}