【问题标题】:Timing problem between State and BlocListener FlutterState 和 BlocListener Flutter 之间的时序问题
【发布时间】:2020-04-10 08:53:33
【问题描述】:

我正在使用flutter_bloc,并且我的MapScreen 抽屉中有一个按钮,该按钮导航到AlarmsScreen 并将Event 发送到该集团,以便AlarmsScreen 接收带有所需数据的State在其 BlocListener 中构建 UI。 我注意到AlarmsScreen 并不总是根据使用State 传入侦听器的数据进行构建,经过几次尝试后,我注意到如果我按下按钮稍长一点(按钮上会出现加载栏??)比AlarmsScreen 总是正确绘制。这意味着,正如 BLocListener 和 Bloc 中的打印结果所证实的那样,有时屏幕会在 State 流式传输之后加载,而 BlocListener 没有捕捉到它,因为它还没有初始化。为了确保我添加了一个延迟 200 毫秒的计时器来发送事件,现在它永远不会失败。 计时器只是一种解决方法,但是有没有办法在屏幕加载时读取块流式传输的最新状态? . 一如既往,非常感谢您的时间和帮助。 这是按钮:

FlatButton.icon(
                          icon: Image.asset(
                            'assets/schedulerButton.png',
                            height: 55,
                            width: 55,
                          ),
                          label: Text(
                            'Check scheduler',
                            style: TextStyle(
                                color: Colors.white,
                                fontSize: 18,
                                fontWeight: FontWeight.w400),
                          ),
                          color: Colors.transparent,
                          onPressed: () {
                            // TODO call LoadAlarms and navigate to SchedulerScreen
                            print('pressed');
                            cache.play('tableViewOpen.mp3');
                            BlocProvider.of<SchedulerBloc>(context)
                                .add(LoadAlarms());
                            Navigator.push(
                              context,
                              MaterialPageRoute(
                                  builder: (_) => BlocProvider.value(
                                        value: BlocProvider.of<SchedulerBloc>(
                                            context),
                                        child: SchedulerScreen(
                                            widget.key, widget.user),
                                      )),
                            );
                            Timer(Duration(milliseconds: 200), () {
                              BlocProvider.of<SchedulerBloc>(context)
                                  .add(LoadAlarms());
                            });
                          },
                        ),

这是屏幕:

class _SchedulerScreenState extends State<SchedulerScreen> {
  AudioCache cache = new AudioCache();

  List<Alarm> alarms = [];
  List<SchedulerCell> cells = [];

  @override
  Widget build(BuildContext context) {
    cache.loadAll(['click.mp3', 'tableViewOpen.mp3', 'tableViewClose.mp3']);
    dynamic backButton =
        Platform.isIOS ? CupertinoIcons.back : Icons.arrow_back;
    dynamic addButton = Platform.isIOS ? CupertinoIcons.add : Icons.add;
    return BlocListener<SchedulerBloc, SchedulerState>(
      listener: (BuildContext context, SchedulerState state) {
        if (state is AlarmsLoaded) {
          setState(() {
            alarms = state.alarms;
            print('ShedulerListener : alarms are $alarms');
            cells = state.cells;
            print('ShedulerListener : cells are $cells');
          });
        }
      },
      child: Scaffold(
        appBar: AppBar(
          elevation: 0,
          backgroundColor: Colors.transparent,
          leading: IconButton(
              icon: Icon(backButton),
              color: Colors.redAccent,
              onPressed: () {
                cache.play('tableViewClose.mp3');
                Navigator.pop(context);
              }),
          title: Text(
            'Controlli tragitti',
            textAlign: TextAlign.center,
            style: TextStyle(
                color: Colors.orange,
                fontSize: 22,
                fontWeight: FontWeight.w500,
                letterSpacing: 1),
          ),
          centerTitle: true,
          actions: <Widget>[
            IconButton(
              icon: Icon(addButton),
              color: Colors.redAccent,
              onPressed: () {
                // TODO navigate to AddEditCheckScreen
                cache.play('tableViewOpen.mp3');
                Navigator.push(
                  context,
                  MaterialPageRoute<AddEditCheckScreen>(
                      builder: (_) => BlocProvider.value(
                            value: BlocProvider.of<SchedulerBloc>(context),
                            child: AddEditCheckScreen(
                                key: widget.key,
                                isEditing: false,
                                user: widget.user),
                          )),
                );
              },
            ),
            IconButton(
              icon: Icon(Icons.clear),
              color: Colors.redAccent,
              onPressed: () {
                BlocProvider.of<SchedulerBloc>(context).add(ClearAlarms());
                // TODO navigate to AddEditCheckScreen
                cache.play('tableViewOpen.mp3');
              },
            )
          ],
        ),
        body: ListView.builder(
          padding: EdgeInsets.all(20),
          itemCount: alarms.length,
          itemBuilder: (BuildContext context, int index) => Container(
            color: Colors.redAccent,
            child: cells[index],
          ),
        ),
      ),
    );
  }
}

【问题讨论】:

    标签: flutter bloc


    【解决方案1】:

    尝试添加

    @override
      Stream<Transition<ComplexEvent, ComplexState>> transformEvents(
        Stream<ComplexEvent> events,
        TransitionFunction<ComplexEvent, ComplexState> transitionFn,
      ) {
        return events.switchMap(transitionFn);
      }
    

    到你的 Bloc 班。它将仅执行最新事件并丢弃任何以前的事件。您可以使用https://rxmarbles.com/ 来帮助您理解 rx 概念。

    【讨论】:

    • 您好,感谢您的回答。我需要的实际上是流上可用的最新状态,而不是事件,因此当屏幕加载时,它可以在侦听器中读取它。据我了解 rx 这正是它与普通流相反的作用,后者仅使流式数据可供活动侦听器使用。 Bloc 包面团的行为应该像我需要的那样,就像在 rxdart 上构建的那样......
    • @Vincenzo 我认为问题在于您正在调度一个事件并立即推送新路线。 Bloc 是异步处理的,尽管您没有在您的 bloc 中进行任何长时间的处理,但它可能还没有准备好。我会检查 Bloc 的警报屏幕状态并相应地使用 locBuilder 重建
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-01-06
    • 1970-01-01
    • 2020-05-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-12
    相关资源
    最近更新 更多