从推到顶部的页面更改后,不会产生 Flutter Bloc State

Flutter Bloc State won't be yielded after change from the Page pushed on top

AddWorkoutEvent 已从 PageCreateWorkout[= 正确调度47=] DbMWorkout.

这将被插入到数据库的正确 table 中。 PageCreateWorkout 将收到 WorkoutAddedState 通知使用给定的 workoutId 到 PageWorkoutDetail。路由堆叠在PageSelectWorkout上,其中WorkoutBloc 主要用于显示所有锻炼。在那里 PageSelectWorkout 应该用新的 WorkoutLoadedState 和新给定的 刷新锻炼列表。 (WorkoutList 包含添加的 Workout,我在记录器中检查过;但不会产生 State。请注意,我将 equatable 扩展到 WorkoutStates。)

else if (event is AddWorkoutEvent) {
      logger.i("AddWorkoutEvent | workout: ${event.workout}");
      yield WorkoutLoadingState();
      try {
        DbMWorkout workout = await RepositoryWorkout.repo.add(event.workout);
        yield WorkoutAddedState(id: workout.id);
        List<DbMWorkout> workoutList = await RepositoryWorkout.repo.getAll();
        
        logger.i("AddWorkoutEvent | workoutListLength: ${workoutList.length}");

        yield WorkoutLoadedState(workoutList: workoutList); // <-- this state
      } catch (e) {
        yield WorkoutErrorState(message: e.toString());
      }
    } 

PageSelectWorkout 是 indexedStack 中导航器的初始页面:

IndexedStack(
                sizing: StackFit.expand,
                index: _currentIndex,
                children: <Widget>[
                  Navigator(
                      key: _pageOverview,
                      initialRoute: PageOverview.routeName,
                      onGenerateRoute: (route) =>
                          RouteGenerator.generateRoute(route)),
                  Navigator(
                      key: _pageSelectWorkoutNew,
                      initialRoute: PageSelectWorkout.routeName,
                      onGenerateRoute: (route) =>
                          RouteGenerator.generateRoute(route)),
                  Navigator(
                      key: _pageLog,
                      initialRoute: PageLog.routeName,
                      onGenerateRoute: (route) =>
                          RouteGenerator.generateRoute(route)),
                  Navigator(
                      key: _pageSettings,
                      initialRoute: PageSettings.routeName,
                      onGenerateRoute: (route) =>
                          RouteGenerator.generateRoute(route))
                ]),

到 SelectWorkout 的命名路由在 BlocProvider 中用正确的 Bloc 包装:

case PageSelectWorkout.routeName:
    return CupertinoPageRoute(
        settings: settings,
        builder: (context) {
          return BlocProvider(
              create: (context) => WorkoutBloc(),
              child: PageSelectWorkout());
        });

注意:在 DeleteWorkoutEvent 等其他事件中,在没有导航到另一个页面的情况下发生,更新后的状态会正确生成。

我在检查了一些 GitHub 问题后找到了答案,答案很简单: 因为我想在 2 个不同的页面上访问同一个 Bloc,所以我 不能 只是将 Bloc 的新实例包装到每个页面。

相反,我应该将 BlocProvider 与 WorkoutBloc 包装在 WidgetTree 层次结构中更高的位置,例如 main.dart

之前:

case PageSelectWorkout.routeName:
    return CupertinoPageRoute(
        settings: settings,
        builder: (context) => BlocProvider(
            create: (context) => WorkoutBloc(), // <-- Instance of WorkoutBloc
            child: PageSelectWorkout()));

  case PageCreateWorkout.routeName:
    return CupertinoPageRoute(
        settings: settings,
        builder: (context) => BlocProvider(
              create: (context) => WorkoutBloc(), // <-- Instance of WorkoutBloc
              child: PageCreateWorkout(
                workoutIndex: arguments["workoutIndex"],
                workoutPosition: arguments["workoutPosition"],
              ),
            ));

之后:

case PageSelectWorkout.routeName:
    return CupertinoPageRoute(
        settings: settings, builder: (context) => PageSelectWorkout());

  case PageCreateWorkout.routeName:
    return CupertinoPageRoute(
      settings: settings,
      builder: (context) => PageCreateWorkout(
        workoutIndex: arguments["workoutIndex"],
        workoutPosition: arguments["workoutPosition"],
      ),
    );

及 Inheritance/WidgetTree 层次结构中的更高级别,例如main.dart :

return MaterialApp(
                  debugShowCheckedModeBanner: false,
                  title: Strings.appTitle,
                  theme: AppTheme.darkTheme,
                  home: MultiBlocProvider(providers: [
                    BlocProvider<WorkoutBloc>(
                      create: (context) => WorkoutBloc(), // <-- put the Instance higher
                    ),
                    BlocProvider<NavigationBloc>(
                      create: (context) => NavigationBloc(),
                    ),
                  ], child: BottomNavigationController()));