Flutter BLoC:在父小部件更新时维护子状态

时间:2020-10-28 16:56:09

标签: flutter bloc

我现在有一个可以创建计时器列表的应用。它使用两个BLoC,一个用于单个计时器,另一个用于整体列表。您可以在下面看到列表的示例: Example list

在图像中,您可以看到索引1和2尚未启动索引0和2。我的问题是,每当我在列表中添加或删除项目时,所有计时器都会重置。

是否有一种方法可以在重绘父窗口小部件时保持其状态不变?

这是列表代码:

此处的项目图块包含计时器的BLoC:

\s

最初,我认为这是一个关键问题,因为该列表未正确删除,但是我相信我已经按照示例中显示的方式实现了键,但仍然存在问题。

$

这是在BLoC列表中传递的计时器模型:

  class HomePage extends StatefulWidget {
  static const TextStyle timerTextStyle = TextStyle(
    fontSize: 30,
    fontWeight: FontWeight.bold,
  );

  final Stream shouldTriggerChange;
  HomePage({@required this.shouldTriggerChange});
  @override
  _HomePageState createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  StreamSubscription streamSubscription;

  @override
  initState() {
    super.initState();
    streamSubscription = widget.shouldTriggerChange.listen((data) {
      createTimer(context, data);
    });
  }

  void createTimer(BuildContext context, timer_type timer) {
    BlocProvider.of<ListBloc>(context).add(Add(
        id: DateTime.now().toString(),
        duration: timer == timer_type.timer ? 100 : 0,
        timer: timer,
        timerTextStyle: HomePage.timerTextStyle));
  }

  @override
  didUpdateWidget(HomePage old) {
    super.didUpdateWidget(old);
    // in case the stream instance changed, subscribe to the new one
    if (widget.shouldTriggerChange != old.shouldTriggerChange) {
      streamSubscription.cancel();
      streamSubscription = widget.shouldTriggerChange
          .listen((data) => createTimer(context, data));
    }
  }

  @override
  dispose() {
    super.dispose();
    streamSubscription.cancel();
  }

  @override
  Widget build(BuildContext context) {
    return BlocBuilder<ListBloc, ListState>(
      builder: (context, state) {
        if (state is Failure) {
          return Center(
            child: Text('Oops something went wrong!'),
          );
        }
        if (state is Loaded) {
          return Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              state.timers.isEmpty
                  ? Center(
                      child: Text('no content'),
                    )
                  : Expanded(
                      child: ListView.builder(
                        itemBuilder: (BuildContext context, int index) {
                          return ItemTile(
                            index: index,
                            timer: state.timers[index],
                            onDeletePressed: (id) {
                              BlocProvider.of<ListBloc>(context)
                                  .add(Delete(id: id));
                            },
                          );
                        },
                        itemCount: state.timers.length,
                      ),
                    ),
            ],
          );
        }
        return Center(
          child: CircularProgressIndicator(),
        );
      },
    );
  }
}

任何帮助将不胜感激。

谢谢!

1 个答案:

答案 0 :(得分:1)

每次重建列表时,您都在创建一个新的UniqueKey,这会强制删除该状态

要解决此问题,您必须将密钥与计时器相关联,例如,将计时器包装在一个包含计时器和密钥的类中,例如:

class KeyedTimer {
  final key = UniqueKey();
  Timer timer;
}

因此,现在您将拥有一个KeyedTimer对象列表,而不是计时器列表,并且可以在列表的itembuilder中使用该键