Fai*_*cia 3 flutter flutter-layout
我无法理解为什么我的 Stateful 小部件在重建后没有更新状态。我有一个有状态的小部件,负责每秒递减一个计数器,因此它收到一个初始值,我将此初始值传递给状态并开始递减它。
它还具有一个按钮,当按下该按钮时,会向我的块发送一个事件,该块会使用新的初始值重建有状态小部件,事实是,它确实发送并更新初始值,但计数器继续递减旧值,我没有知道为什么。这是代码示例:
小部件
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}")
],
);
}
}
Run Code Online (Sandbox Code Playgroud)
集团
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];
}
Run Code Online (Sandbox Code Playgroud)
先感谢您。
这是因为您只Timer在您的 上设置了您Counter的,每个小部件生命周期仅initState调用一次。
基本上,当您Counter第一次构建时,它将调用initState(),并且只要它保留在该小部件树中,只有didUpdateWidget()和/或didChangeDependencies()将被调用以更新该 小部件(例如,当使用新参数重建时,就像您正在做的那样) )。
方法也会发生同样的情况,这与仅调用一次dispose()相反,但这次是在从树中删除小部件时调用。initState()
另外,您在这里使用状态的方式是错误的。您不需要将参数传递给状态本身(就像您所做的那样:
CounterState createState() => CounterState(this.initialValue);
Run Code Online (Sandbox Code Playgroud)
相反,您可以通过调用以下方式访问该小部件中的所有参数:widget.initialValue。
因此,综上所述,基本上,您要做的就是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}")
],
);
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3160 次 |
| 最近记录: |