有状态的小部件在BLOC状态更改后未重建

问题描述 投票:0回答:1

我很难理解为什么有状态小部件在重建后没有更新状态。我有一个有状态的小部件,负责每秒减少一个计数器,因此它接收到一个初始值,我将此初始值传递给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];
}

谢谢你。

flutter flutter-layout
1个回答
0
投票

这是因为您只在TimerCounter上设置了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}")
      ],
    );
  }
}
© www.soinside.com 2019 - 2024. All rights reserved.