I am using Bloc for my application, however I was doing something wrong and that is, providing all BlocProvider creates in the MaterialApp
and I would not like to follow that bad practice.
Let's suppose that when I navigate to ScreenA, we create the Bloc as follows :
case PageNames.screenA:
return PageTransition( // Some class that navigates
duration: const Duration(milliseconds: 400),
child: BlocProvider<ScreenABloc>(
create: (context) => ScreenABloc(),
child: const ScreenAPage(),
),
);
Now inside ScreenA, I will do a navigation to ScreenB, and everything is fine, however inside ScreenB at the bottom of my widget tree I want to access the ScreenABloc again, but I can't assign a BlocProvider.value
because I get :
ProviderNotFoundException (Error: Could not find the correct Provider<ScreenABloc> above this Welcome Widget
return BlocProvider.value(
value: BlocProvider.of<ScreenABloc>(context),
child: child ...
);
So I am not sure how to get the supplier that has already been created, or if I should re-create it or what to do in those cases.
Using all BlocProviders
in the starting of the file is not always considered bad practice. as according to official docs
By default,
BlocProvider
will create the bloclazily
, meaning create will get executed when the bloc is looked up via BlocProvider.of(context).
So now, What are the use cases to use providers
globally?
When you want to access the providers almost everywhere in the app.
When to use providers
passing through routes ?
When only some screens needs access to the
bloc
you can pass value usingBlocProvider.value
According to the official docs of BlocProvider
in flutter_bloc
,follow these steps to pass BlocProvider
to the child screen.
BlocA()
BlocProvider(
lazy: false,
create: (BuildContext context) => BlocA(),
child: ChildA(),
);
BlocA
to ScreenA()
Make sure this is called from inside the ChildA()
BlocProvider.value(
value: BlocProvider.of<BlocA>(context),
child: ScreenA(),
);
ChildA
or ScreenA
retrieve value as:// with extensions
context.read<BlocA>();
// without extensions
BlocProvider.of<BlocA>(context);