Reputation: 3288
I am looking for the most convenient way to share bloc in different screens/pages without providing at top of the material app. For example I have a Customer
bloc, which is required in CustomerListScreen
and CustomerDetailsScreen
. The bloc is created in CustomerListScreen
and passed it to the CustomerDetailsScreen
while navigating.
Navigator.context, MaterialPageRoute(builder: (context) => CustomerDetailsScreen(context.read<CustomerBloc>())));
This is the procedure I am following right now. Looking for any better approach available out there..
Upvotes: 9
Views: 11516
Reputation: 3152
Change the context name to other name and pass that context like below
@override
Widget build(BuildContext context) {
return MultiBlocProvider(
providers: [
BlocProvider<AuthBloc>(
create: (BuildContext context) => AuthBloc(),
),
],
child: Scaffold(
appBar: AppBar(
title: const Text("Log In"),
centerTitle: true,
backgroundColor: ContactColors.primaryColor,
),
backgroundColor: ContactColors.offwhite,
body: BlocConsumer<AuthBloc, AuthState>(listener: (c, state) {
if (state is AuthError) {
print("error state");
} else if (state is AuthSuccess) {
print("success");
}
}, builder: (c, state) {
if (state is AuthLoading) {
print("loader");
return loginbox(c);
} else {
return loginbox(c);
}
// return widget here based on BlocA's state
})));
}
Upvotes: -1
Reputation: 408
You could make the Bloc a required field of the page, something like this:
class CustomerDetailsScreen extends StatelessWidget {
CustomerDetailsScreen(this.mybloc);
final Bloc mybloc;
@override
Widget build(BuildContext context) {
return BlocProvider.value(
value: mybloc,
child: Text('Body...'),
);
}
}
Now, even if you use a package like AutoRoute you will still be able to provide the bloc to the page route.
Even though I don't like this solution because what if you navigated through a url then you can't pass the bloc to it, for this i recommend to use nested navigation read this
it will look something like this if you use AutoRoute
@MaterialAutoRouter(
replaceInRouteName: 'Page,Route',
routes: <AutoRoute>[
AutoRoute(
page: BlocProviderPage,
children: [
AutoRoute(page: CustomerListScreen),
AutoRoute(page: CustomerDetailsScreen),
],
),
],
)
class $AppRouter {}
class BlocProviderPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return BlocProvider(
create: (context) => MyBloc(),
child: AutoRouter(),
);
}
}
This way both pages will have access to the bloc and you cant navigate to them without a BlocProviderPage
being a parent of them
Upvotes: 6
Reputation: 8320
Use BlocProvider.value.
BlocProvider can be used to provide an existing bloc to a new portion of the widget tree. This will be most commonly used when an existing bloc needs to be made available to a new route. In this case, BlocProvider will not automatically close the bloc since it did not create it.
BlocProvider.value(
value: context.read<CustomerBloc>(),
child: CustomerDetailsScreen(),
);
Upvotes: 11