Flutter bloc Cubit出现问题:在调用close后无法发出新状态

3

我有一个使用Cubit构建的应用程序,其中包括两个页面A和B。每个页面都可以正常工作。我在两个页面上都使用了一个更改状态的Cubit,但是当我转到第二个页面并弹出以返回第一个页面时,标题上会出现错误。我使用get it注入依赖项。

A页面路由

routes: {
        '/home': (context) => MultiBlocProvider(providers: [
              BlocProvider<ChangeStatusCubit>(
                create: (context) => locator<ChangeStatusCubit>(),
              ),
            ], child: const TodoHomePage()),

路由B

'/details': (context) => MultiBlocProvider(
            providers: [
              BlocProvider<ChangeStatusCubit>(
                create: (context) => locator<ChangeStatusCubit>(),
              ),
            ],
            child: TodoDetailsPage(),

依赖注入
locator.registerLazySingleton<ChangeStatusCubit>(() => ChangeStatusCubit(
        locator(),
      ));

立方尺(cubit)
changeStatus(int id) async {
    emit(ChangeStatusLoading());
    try {
      ResponseModel response = await _changeStatusUseCase(id);
      if (response.status == 200) {
        emit(ChangeStatusLoaded(response.data));
      } else {
        emit(ChangeStatusError(response.error?.todo?.first ?? ""));
      }
    } catch (e) {
      emit(ChangeStatusError(e.toString()));
    }
  }
2个回答

10
当您使用create来初始化BlocProvider的bloc时,当该BlocProvider被卸载时,bloc的流将关闭。
为了解决这个问题,您可以将BlocProvider移动到更高的小部件树中,以便在页面之间保持已安装状态,或者您可以使用BlocProvider.value构造函数。
后者可能是最好的选择,因为您实际上并没有创建一个bloc,而是利用了一个预先存在的单例。虽然将小部件向上移动也是有意义的,这样它就是Navigator的父级 - 这样您只需声明一次即可减少代码重复。
但是,在您的示例中保持结构不变,您的代码可能如下所示:
routes: {
    '/home': (context) => MultiBlocProvider(
        providers: [
            BlocProvider.value<ChangeStatusCubit>(
                value: locator<ChangeStatusCubit>(),
            ),
        ],
        child: const TodoHomePage(),
    ),
    '/details': (context) => MultiBlocProvider(
        providers: [
            BlocProvider<ChangeStatusCubit>.value(
                value: locator<ChangeStatusCubit>(),
            ),
        ],
        child: TodoDetailsPage(),
    ),
}

先生,您启发了我,谢谢。 - Ardeshir ojan

0
我不是一个非常熟练的"Flutterrer",所以我在一个类似的问题上苦苦挣扎了很长时间,但是在稍微不同的环境中。我希望这个描述能帮助到别人。
我的应用程序使用了几个cubit。其中一些是在main.dart方法中"提供"的(请参见下面的代码片段),一些是在特定的屏幕和小部件中提供的。

main.dart

runApp(
      MultiProvider(
        providers: [
          ChangeNotifierProvider(create: (_) => ConnectionService()..start()),
          ],
        child: MultiBlocProvider(
          providers: [
            BlocProvider(
              create: (_) => GetIt.I.get<MessagesCubit>()..fetchMessages(),
            ),
            ....
            BlocProvider(create: (_) => GetIt.I.get<JobListCubit>()),
            BlocProvider(create: (_) => GetIt.I.get<LogoutCubit>()),
          ],
          child: MaterialApp(
            navigatorKey: navigatorKey,
            title: 'MyAPP',
            theme: ThemeData(
                   ...                ),
            initialRoute: AuthRouter.landing,
            onGenerateRoute: Routes.router.generator,
            builder: (context, child) {
              return GlobalErrorHandlerWidget(child: child!);
            },
          ),
        ),
      ),
    ),

我的导航由Fluro路由器处理,就像这样一个:

home_router.dart

class HomeRouter {
  HomeRouter(this.router);

  final FluroRouter router;

  static const String homePage = "/home-page";
  static const String jobScreenViewCreator = "/job-screens-view-creator";

  void register() {
    router.define(
      homePage,
      handler: Handler(
        handlerFunc: (
          BuildContext? context,
          Map<String, List<String>> params,
        ) {
          return MultiBlocProvider(
            providers: [
              //// BlocProvider(
              ////   create: (_) => GetIt.I.get<JobListCubit>(),
              //// ),

              BlocProvider(
                create: (_) => GetIt.I.get<JobDescriptionListCubit>(),
              ),
            ],
            child: const HomePage(),
          );
        },
      ),
      transitionType: TransitionType.native,
    );

    router.define(
      jobScreenViewCreator,
      handler: Handler(
        .....
    );
  }
}

请注意上面首页路由中的注释的BlocProvider。这是导致状态错误的冒犯代码,因为它与首页上的Cubit初始化发生冲突。 请注意,对我来说,使用didChangeDependencies而不是initState的建议并没有起作用。下面的代码运行良好。

home_page.dart

 class HomePage extends StatefulWidget {
      const HomePage({Key? key}) : super(key: key);
    
      @override
      HomePageState createState() => HomePageState();
    }
    
    class HomePageState extends State<HomePage> {
     
  @override
  void initState() {
    _onInit();
    super.initState();
  }

  void _onInit() async {
    await BlocProvider.of<JobListCubit>(context).fetchJobs();
  }
    
      
    
      @override
      Widget build(BuildContext context) {
        return BlocBuilder<JobListCubit, JobListState>(
                            builder: (context, state) {
                          ...
                          }
                  

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接