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. TheMultiBlocProvider
is 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 beingBloc
maintains the state changes and creation and destruction ofBloc
's andCubit
's. If you just inject it's instance, thenBlocProvider
will always get the same instance with previous states and all. This will cause us to manually reset the state ofBloc
leading to unnecessary state management which is against theBloc
's principles of state management.Event
s should update states not us.Bloc
should not meDI
ed. However, the dependencies used byBloc
can beDI
ed. FOr instance,repository
anddata sources
can be injected into theBloc
. But never theBloc
itself.
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.