Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
348 views
in Technique[技术] by (71.8m points)

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

The AddWorkoutEvent is dispatched correctly from the PageCreateWorkout with a DbMWorkout.

This will be inserted in the correct table of the DB. The PageCreateWorkout will be notified with the WorkoutAddedState to go to PageWorkoutDetail with the given workoutId. The routes are stacked on the PageSelectWorkout, in which the WorkoutBloc is mainly used, to show all workouts. In there the PageSelectWorkout shall be refreshed with the new WorkoutLoadedState with the newly given workoutList. (The WorkoutList contains the added Workout, which I checked in the logger; but the State won't be yielded. Note that I am extending equatable to 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());
      }
    } 

The PageSelectWorkout is the initialPage of a Navigator in an 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))
                ]),

The named Route to the SelectWorkout is wrapped with the correct Bloc in a BlocProvider:

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

Note: In other Events like DeleteWorkoutEvent , which is happening without navigating to another Page, the updated State gets yielded correctly.

question from:https://stackoverflow.com/questions/65861580/flutter-bloc-state-wont-be-yielded-after-change-from-the-page-pushed-on-top

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

I found the answer after checking out some GitHub Issues and it's rather simple: Since I want to access the same Bloc on 2 different Pages I can not just wrap a new Instance of the Bloc to each of the Page.

Instead I should wrap the BlocProvider with the WorkoutBloc higher in the WidgetTree Hierarchy for example in the main.dart

Before:

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"],
              ),
            ));

After:

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"],
      ),
    );

and higher in the Inheritance/WidgetTree Hierarchy e.g. 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()));

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...