【问题标题】:Stateful Widget not rebuilding after BLOC state change有状态的小部件在 BLOC 状态更改后未重建
【发布时间】:2020-04-17 19:15:34
【问题描述】:

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

    那是因为您只在Counter 的initState 上设置Timer,每个小部件生命周期仅调用一次。

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

    dispose() 方法也会发生同样的情况,这与 initState() 的相反方法只调用了一次,但这一次是从树中删除小部件时。

    另外,你在这里使用了错误的状态。您不需要将参数传递给状态本身(就像您正在做的那样:

     CounterState createState() => CounterState(this.initialValue);
    

    但是,您可以通过调用: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}")
          ],
        );
      }
    }
    

    【讨论】:

    • 这是一个很好的答案,非常感谢!我以为当我发送新状态时,BlocBuilder 会从树中删除 Widget,构建一个新状态并将其添加到树中,但我想我错过了,对吧?如果你有时间,你能给我简要解释一下到底发生了什么吗?它只是用新值更新了吗?再次感谢您
    • 这里你对小部件的生命周期有一个很好的解释:flutterbyexample.com/stateful-widget-lifecycle
    猜你喜欢
    • 2020-04-25
    • 1970-01-01
    • 2020-03-10
    • 2021-06-24
    • 2021-06-17
    • 2020-06-17
    • 2020-07-05
    • 2021-10-22
    • 2020-03-18
    相关资源
    最近更新 更多