Is there anyway that I can use MultiBlocProvider to clean this nest of widgets up?

Issue

I’m trying to clean this mess of widgets up but I have found no way to do so. My NavigationBloc depends on the stream provided by AuthenticationBloc and to prevent memory leaks I have to close the stream.

The Builder widget is required so that I can get the latest BuildContext provided by BlocProvider but I know that MultiBlocProvider would clean this up tremendously. I’d like to avoid wrapping this widget in the runApp function but it’s an option I guess.

class _MyAppState extends State<MyApp> {
  final authRepo = AuthRepo();
  AuthenticationBloc authBloc;

  @override
  void dispose() {
    authBloc?.close();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return BlocProvider<AuthenticationBloc>(
      create: (_) =>
          AuthenticationBloc(authRepo: authRepo)..add(InitializeAuth()),
      child: Builder(builder: (context) {
        authBloc = context.bloc<AuthenticationBloc>();
        return BlocProvider<NavigationBloc>(
          create: (_) => NavigationBloc(authBloc),
          child: MaterialApp(
            title: 'Arrow Manager',
            debugShowCheckedModeBanner: false,
            theme: appTheme(),
            builder:
                ExtendedNavigator<Router>(router: Router(), initialRoute: '/'),
          ),
        );
      }),
    );
  }
}

Solution

As you say, you can use the MultiProvider to avoid having nested providers

You have to create your AuthenticationBloc in the initState() method

class _MyAppState extends State<MyApp> {
  final authRepo = AuthRepo();
  AuthenticationBloc authBloc;

  @override
  void initState() {
    super.initState();
    authBloc = AuthenticationBloc(authRepo: authRepo);
  }

  @override
  void dispose() {
    authBloc?.close();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return MultiBlocProvider(
      providers: [
        BlocProvider(
          create: (_) => authBloc..add(InitializeAuth()),
        ),
        BlocProvider(
          create: (context) => NavigationBloc(authBloc),
        ),
      ],
      child: Builder(
        builder: (context) {
          authBloc = context.bloc<AuthenticationBloc>();
          return MaterialApp(
            title: 'Arrow Manager',
            debugShowCheckedModeBanner: false,
            theme: appTheme(),
            builder: ExtendedNavigator<Router>(router: Router(), initialRoute: '/'),
          );
        },
      ),
    );
  }
}

Answered By – F Perroch

Answer Checked By – Katrina (FlutterFixes Volunteer)

Leave a Reply

Your email address will not be published. Required fields are marked *