Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to set correctly the BlocProvider between two different routes (screens)?

Tags:

flutter

dart

bloc

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.

like image 201
Daniel Roldán Avatar asked Sep 05 '25 03:09

Daniel Roldán


2 Answers

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 bloc lazily, 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 using BlocProvider.value


According to the official docs of BlocProvider in flutter_bloc,follow these steps to pass BlocProvider to the child screen.

Creation of BlocA()

BlocProvider(
  lazy: false,
  create: (BuildContext context) => BlocA(),
  child: ChildA(),
);

Passing the value of BlocA to ScreenA()

Make sure this is called from inside the ChildA()

BlocProvider.value(
  value: BlocProvider.of<BlocA>(context),
  child: ScreenA(),
);

Now either from ChildA or ScreenA retrieve value as:

// with extensions
context.read<BlocA>();

// without extensions
BlocProvider.of<BlocA>(context);
like image 157
krishnaacharyaa Avatar answered Sep 07 '25 22:09

krishnaacharyaa


You can create a method of creating BlocProvider in the screen itself, then you can use that method for navigating and creating providers for you.

Here's an example:

class MyWidget extends StatelessWidget {
  const MyWidget({super.key});

   static Widget create() {
    return MultiBlocProvider(
      providers: [
        BlocProvider<SignInBloc>(
          create: (BuildContext context) => SignInBloc(),
        ),
      ],
      child: const SignInScreen(),
    );
  }

  @override
  Widget build(BuildContext context) {
    return Container();
  }
}
like image 26
Cavin Macwan Avatar answered Sep 07 '25 22:09

Cavin Macwan