从推到顶部的页面更改后,不会产生 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()));
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()));