Im making a type of chat app, and has a need for multiple blocs/repositories/etc. This has lead to my widget tree looking like this:
And also has lead to a nasty looking build method in my 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,
),
),
),
);
}
Is this normal? I looked into GetIt, but i read that it is difficult to do dependency injection with blocs. Not sure if this is a fixable issue, or if this is just how working with multiple blocs work. Thank you!
CodePudding user response:
Q: Is this normal?
A: Yes, this is perfectly normal. TheMultiBlocProvideris used in the same way and this is the resulting tree structure.
Q: I looked into GetIt, but i read that it is difficult to do dependency injection with blocs
A: No, it's not difficult to do DI with Blocs. Rather its very simple. And, it's just like injecting other instance. However, there is a cost and problem associated with it.
You can inject using below code:
return BlocProvider(
create: (ctx) => getIt<SomeBloc>(),
child: SomeChildWidget(),
);
To use getIt with Bloc, there is only one problem that must be addressed properly.
Bloc's cannot and must not be dependency injected in Flutter usinggetIt. The reason beingBlocmaintains the state changes and creation and destruction ofBloc's andCubit's. If you just inject it's instance, thenBlocProviderwill always get the same instance with previous states and all. This will cause us to manually reset the state ofBlocleading to unnecessary state management which is against theBloc's principles of state management.Events should update states not us.Blocshould not meDIed. However, the dependencies used byBloccan beDIed. FOr instance,repositoryanddata sourcescan be injected into theBloc. But never theBlocitself.
We use Bloc extensively with GetIt, just that we do not use it on the Bloc instance itself, rather with the dependencies needed for the Bloc's.

