Flutter BLoC mapEventToState仅在事件第一次被调用时,而下次每次触发该事件时都不会被调用 [英] Flutter BLoC mapEventToState gets called only the first time for an event and not called each next time that event is fired

查看:190
本文介绍了Flutter BLoC mapEventToState仅在事件第一次被调用时,而下次每次触发该事件时都不会被调用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有 Courses Tasks .每个 Course (课程)都有许多 Tasks(任务).这就是为什么我在应用程序中使用不同的屏幕来显示课程列表,并在点击课程后导航到下一个屏幕-任务列表.这是我的课程列表的 onTap 方法:

I have Courses and Tasks. Each Course has many Tasks. That is why I am using different screens in the app to show a list of courses and after a tap on a course, I am navigating to the next screen - a list of tasks. Here is my onTap method of the list of courses:

                          onTap: () {
                            TasksPageLoadedEvent pageLoadedEvent =
                                TasksPageLoadedEvent(
                              courseId: state.courses[index].id,
                              truckNumber: this.truckNumber,
                            );
                            serviceLocator<TaskBloc>().add(pageLoadedEvent);
                            Routes.sailor(
                              Routes.taskScreen,
                              params: {
                                Routes.courseNumber:
                                    state.courses[index].courseNumber,
                                Routes.truckNumber: this.truckNumber,
                                Routes.courseId: state.courses[index].id,
                              },
                            );
                          }

我创建一个 TasksPageLoadedEvent ,将其传递给 TaskBloc ,然后导航至任务"页面.

I create a TasksPageLoadedEvent, pass it to the TaskBloc and navigate to the Tasks page.

这是 TaskBloc 以及它如何处理映射事件-状态:

Here is the TaskBloc and how it handles the mapping Event - State:

@override
  Stream<TaskState> mapEventToState(
    TaskEvent event,
  ) async* {
    if (event is TasksLoadingEvent) {
      yield TasksLoadingState();
    } else if (event is TasksReloadingErrorEvent) {
      yield TasksErrorState();
    } else if (event is TasksFetchedFailureEvent) {
      yield TaskFetchedStateFailureState(error: event.failure);
    } else if (event is TasksPulledFromServerEvent) {
      yield TasksPulledFromServerState(
        truckNumber: event.truckNumber,
        courseNumber: event.courseNumber,
        courseId: event.courseId,
      );
    } else if (event is TasksPageLoadedEvent) {
      yield TasksLoadingState();

      final networkInfoEither = await this.getNetworkInfoQuery(NoQueryParams());

      yield* networkInfoEither.fold((failure) async* {
        yield TasksErrorState();
      }, (success) async* {
        if (success) {
          final getTasksEither = await getTasksQuery(
            GetTasksParams(
              truckNumber: event.truckNumber,
              courseId: event.courseId,
            ),
          );

          yield* getTasksEither.fold((failure) async* {
            yield TaskFetchedStateFailureState(error: "coursesDatabaseError");
          }, (result) async* {
            if (result != null) {
              yield TasksFetchedState(tasks: result);
            } else {
              yield TaskFetchedStateFailureState(
                  error: "coursesFetchFromDatabaseError");
            }
          });
        } else {
          yield TasksNoInternetState();
        }
      });
    }
  }

当我导航到任务"页面时, BlocBuilder 检查状态并相应地处理建筑物.我有一个返回"功能,可以导航回到课程"页面:

When I get navigated to the Tasks page, the BlocBuilder checks the state and handles the building accordingly. I have a Go Back functionality that navigates back to the Courses page:

              onPressed: () {
                serviceLocator<CourseBloc>().add(
                  CoursesPageLoadedEvent(truckNumber: this.truckNumber),
                );
                Navigator.of(context).pop(true);
              },

这会触发上一页的类似事件,并且会重新加载该事件.

This fires the similar event for the previous page and it gets re-loaded.

如果我想去另一门课程并查看其任务,就会遇到我面临的问题.如果我点击列表中的另一个项目并因此触发一个新的 TasksPageLoadedEvent (具有新属性),则根本不会调用 mapEventToState().

The problem I am facing happens if I want to go to another course and see its tasks. If I tap on another item in the list and therefore fire a new TasksPageLoadedEvent (with new properties) the mapEventToState() doesn't get called at all.

我以前在BLoC上也遇到过类似的问题,但是他们在讨论 BlocListener 和扩展 Equatable 的状态.这就是为什么我的事件没有扩展 Equatable 的原因(尽管我不确定这是否是这里的问题).但是仍然没有任何反应.

I have had similar issues with BLoC before, but they were regarding the BlocListener and states extending Equatable. That is why I had my events NOT extending Equatable (although I am not sure whether this was the issue here). But still nothing happens.

这是我的活动:

abstract class TaskEvent {
  const TaskEvent();
}

class TasksPageLoadedEvent extends TaskEvent {
  final String truckNumber;
  final int courseId;

  TasksPageLoadedEvent({
    this.truckNumber,
    this.courseId,
  });
}

class TasksFetchedFailureEvent extends TaskEvent {
  final String failure;

  TasksFetchedFailureEvent({
    this.failure,
  });
}

class TasksLoadingEvent extends TaskEvent {}

class TasksReloadingErrorEvent extends TaskEvent {}

class TasksPulledFromServerEvent extends TaskEvent {
  final String courseNumber;
  final String truckNumber;
  final int courseId;

  TasksPulledFromServerEvent({
    @required this.courseNumber,
    @required this.truckNumber,
    @required this.courseId,
  });
}

我应该如何在每个页面之间使用两个BLoC来处理我的来回页面?

How should I handle my back-and-forth between the two pages using two BLoCs for each page?

推荐答案

好的,我自己找到了答案!

OK, I found an answer myself!

当然,正如费德里克·乔纳森(Federick Jonathan)所暗示的那样,问题是集团的实例.我正在使用由flutter包get_it创建的单例实例.如果您要实现依赖项注入(例如,用于干净的体系结构),这真的很有用.

The problem, of course, as Federick Jonathan implied - the instance of the bloc. I am using a singleton instance created by the flutter package get_it. Which is really useful if you are implementing dependency injection (for a clean architecture for example).

所以一个实例就是问题.

So the one instance was the problem.

幸运的是,该程序包已经实现了整洁的方法 resetLazySingleton< T> .

Luckily the package has implemented the neat method resetLazySingleton<T>.

在返回时调用它会重置该小部件中使用的块.因此,当我再次导航到任务"页面时,我正在使用该块的相同实例,但重置了该实例.

Calling it upon going back resets the bloc used in that widget. Therefore when I navigate again to the Tasks page I am working with the same but reset instance of that bloc.

Future<bool> _onWillPop() async {
    serviceLocator.resetLazySingleton<TaskBloc>(
      instance: serviceLocator<TaskBloc>(),
    );

    return true;
  }

我希望这个答案能够帮助遇到单例,依赖注入以及在带有bloc的Flutter应用程序中来回走动的人.

I hope this answer would help someone in trouble with singletons, dependency injections and going back and forth within a flutter app with bloc.

这篇关于Flutter BLoC mapEventToState仅在事件第一次被调用时,而下次每次触发该事件时都不会被调用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆