Flutter:许多区块提供商使小部件树变得混乱

Rud*_*ter 6 refactoring dependency-injection state-management flutter bloc

我正在制作一种聊天应用程序,并且需要多个块/存储库/等。这导致我的小部件树看起来像这样:

在此输入图像描述

并且还导致了我的 main.dart 中看起来令人讨厌的构建方法:

  @override
  Widget build(BuildContext context) {
    return MultiRepositoryProvider(
      providers: [
        RepositoryProvider(
          create: (_) => AuthRepository(),
        ),
        RepositoryProvider(
          create: (_) => FirestoreRepository(),
        ),
        RepositoryProvider(
          create: (context) => StorageRepository(),
        ),
        RepositoryProvider(
          create: (context) => MessagingRepository(),
        ),
      ],
      child: MultiBlocProvider(
        providers: [
          BlocProvider<AuthBloc>(
            create: (context) => AuthBloc(
              authRepository: context.read<AuthRepository>(),
            ),
          ),
          BlocProvider<BottomnavbarCubit>(
            create: (context) => BottomnavbarCubit(),
            child: MainPage(),
          ),
          BlocProvider<SignupCubit>(
            create: (context) => SignupCubit(
              authRepository: context.read<AuthRepository>(),
            ),
          ),
          BlocProvider<LocaluserCubit>(
            create: (context) => LocaluserCubit(),
            child: MaterialApp(),
          ),
          BlocProvider<SigninCubit>(
            create: (context) => SigninCubit(
              authRepository: context.read<AuthRepository>(),
            ),
          ),
          BlocProvider<UpdateCubit>(
            create: (context) => UpdateCubit(
              firestoreRepository: context.read<FirestoreRepository>(),
            ),
          ),
          BlocProvider<ProfileBloc>(
              create: (context) => ProfileBloc(
                    authBloc: BlocProvider.of<AuthBloc>(context),
                    databaseRepository: context.read<FirestoreRepository>(),
                  )),
          BlocProvider<VoteBloc>(
              create: (context) => VoteBloc(
                  firestoreRepository: context.read<FirestoreRepository>())),
          BlocProvider<MessageBloc>(
              create: (context) => MessageBloc(
                  firestoreRepository: context.read<FirestoreRepository>())),
          BlocProvider<LeaderboardBloc>(
              create: (context) => LeaderboardBloc(
                  databaseRepository: context.read<FirestoreRepository>())),
          BlocProvider<CommentBloc>(
              create: (context) => CommentBloc(
                  firestoreRepository: context.read<FirestoreRepository>())),
          BlocProvider<EditbioCubit>(
            create: (context) => EditbioCubit(),
          ),
          BlocProvider<CommentCubit>(
            create: (context) => CommentCubit(),
          ),
          BlocProvider<SearchBloc>(
            create: (context) => SearchBloc(),
          ),
          BlocProvider(
            create: (context) => SwipeBloc(
              firestoreRepository: context.read<FirestoreRepository>(),
              profileBloc: context.read<ProfileBloc>(),
            ),
          ),
          BlocProvider<StingrayBloc>(
              create: (context) => StingrayBloc(
                    authBloc: BlocProvider.of<AuthBloc>(context),
                    databaseRepository: context.read<FirestoreRepository>(),
                  )),
        ],
        child: MultiProvider(
          providers: [
            Provider<AuthRepository>(
              create: (_) => AuthRepository(),
            ),
            StreamProvider<List<Stingray?>>.value(
              value: FirestoreRepository().stingrays,
              initialData: [],
            ),
          ],
          child: MaterialApp(
            title: 'Fishbowl',
            theme: theme(),
            onGenerateRoute: AppRouter.onGenerateRoute,
            initialRoute: Wrapper.routeName,
          ),
        ),
      ),
    );
  }
Run Code Online (Sandbox Code Playgroud)

这是正常的吗?我研究了 GetIt,但我读到很难用块进行依赖注入。不确定这是否是一个可以解决的问题,或者这是否就是与多个区块一起工作的方式。谢谢你!

Ari*_*iel 8

问: 这正常吗?
答:是的,这是完全正常的。以相同的方式使用,这MultiBlocProvider就是生成的树结构。

问:我研究了 GetIt,但我读到用 Bloc 进行依赖注入很困难。
A:不,用 Bloc 进行 DI 并不困难。相反,它非常简单。而且,这就像注入其他实例一样。然而,存在与之相关的成本和问题。

您可以使用以下代码进行注入:

return BlocProvider(
create: (ctx) => getIt<SomeBloc>(),
child: SomeChildWidget(),
);
Run Code Online (Sandbox Code Playgroud)

要使用getItwith Bloc,只有一个问题必须正确解决。

  1. Bloc不能也不得使用 Flutter 进行依赖注入getIt。原因是维持's 和'sBloc的状态变化以及创建和销毁。如果您只是注入它的实例,那么将始终获得与先前状态和所有状态相同的实例。这会导致我们手动重置状态,导致不必要的状态管理,违背了状态管理的原则。s应该更新状态而不是我们。BlocCubitBlocProviderBlocBlocEvent

  2. Bloc不应该是我DI编的。Bloc但是,可以编辑使用的依赖项DI。例如,repository并且data sources可以注入到Bloc. 但从来没有它Bloc本身。

我们Bloc广泛使用GetIt,只是我们不在Bloc实例本身上使用它,而是与 所需的依赖项一起使用Bloc

更新::

我们也可以使用@injectable来创建 的新实例。BLoC但是,当我们需要根据用法在构造函数中传递参数时BLoC,我个人不会手动创建它们。