BLOC状态更改后,有状态小部件无法重建

时间:2019-12-28 00:14:17

标签: flutter flutter-layout

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

谢谢。

1 个答案:

答案 0 :(得分:1)

这是因为您仅在Timer的{​​{1}}上设置Counter,每个小部件生命周期都将其设置为 only

基本上,第一次构建initState时,它将调用Counter,只要它保留在该小部件树中,就只会initState()和/或didUpdateWidget()被调用以更新那个小部件(例如,当您使用新参数重建时,就像您正在做的那样)。

didChangeDependencies()方法也会发生同样的情况,这与dispose()仅被称为一次的方法相反,但是这次是从树中删除窗口小部件。

此外,您在此处使用错误的状态。您不需要将参数传递给状态本身(就像您所做的那样:

initState()

但是,相反,您可以通过调用 CounterState createState() => CounterState(this.initialValue); 从该窗口小部件访问所有参数。

因此,基本上,您要做的就是基于新更新来更新widget.initialValue小部件,如下所示:

Counter