skip to Main Content

I’ve started using Bloc in my project. I’ve one confusion that I want to clear. Suppose I have got the following cubits:

--- Auth Cubit
--- Category Cubit
--- Cart Cubit
--- Orders Cubit

Now, in order to add them to the project I’ve two options. Either I use MultiBlocProvider and initialized all of them in the main.dart app or I use scopped approach. In the case of scopped approach, flutter will initialize it over and over.

From my understanding, if I initialize providers globally I will be able to remove or update them easily. However, in scopped case, I’ve to change it in multiple classes.

I want to know which approach is best performance-wise and what could be the pros and cons of both approaches.

4

Answers


  1. I haven‘t measured the performance of my approach, but my approach is the following:

    Bloc‘s that use the same data multiple times in a session, I instantiate in main or app. This would be auth. and cart, maybe category.

    Bloc‘s that always run with a new set of data, I instantiate on occasion such as editing an entry of a list of things. This might be Order in your case, if this is the process of checking-out

    Login or Signup to reply.
  2. According to flutter_bloc

    By default, BlocProvider will create the bloc lazily, meaning create will get executed when the bloc is looked up via BlocProvider.of(context).

    Hence it is better to use MultiBlocProvider and initialize all the Cubits at the start of the app. Performance in taken care by the BlocProvider

    BlocProvider should be used to create new blocs which will be made available to the rest of the subtree. In this case, since BlocProvider is responsible for creating the bloc, it will automatically handle closing it.
    MultiBlocProvider(
      providers: [
        BlocProvider<BlocA>(
          create: (BuildContext context) => BlocA(),
        ),
        BlocProvider<BlocB>(
          create: (BuildContext context) => BlocB(),
        ),
        BlocProvider<BlocC>(
          create: (BuildContext context) => BlocC(),
        ),
      ],
      child: ChildA(),
    )
    
    Login or Signup to reply.
  3. I would say that using a global BlocProvider or a scoped one really depends on the use of it, as in your example you did say that you have an Auth Cubit, I assume that this refers to Authentication, right?

    This cubit should handle/listen to user authentication status across the whole app, so you will need to make it accessible by a global bloc provider, otherwise, if you choose as an example to make it available only on a login/sign-up screens, a simple Flutter navigation will make a new widget sub-tree in the Navigator widget in MaterialApp, when you will try to logout as an example from the new screen, it will throw you the usual issue of Error: Could not find the correct BlocProvider..., unless you will pass it with BlocProvider.value, which is very painful and lead you to unnecessary work, right?

    So here before thinking about what is the more preferment, think about the requirement of your app with that specific bloc!

    for another example, such as the categories Cubit, if you fetch them to from a database for example using a repository, a global cubit will be initialized just once time for the global app state, fetching all categories available and showing them, while the user navigates between the screens, the categories will be available always as the previous state ( you might give users opportunity to reload them ), but setting here a nested cubit will initialize the cubit with the repository each time the screen is pushed and popped throw the Navigator, which leads to unnecessary fetches from the database ( and if you use Firebase Firestore, this will lead to unnecessary billed reads in the app ), so also for this you should consider using a global cubit.

    I hope you understand the idea that each case requires you to take a decision while developing the app!

    Now let’s talk about the performance of each one:

    As from the official BloC documentation:

    By default, BlocProvider will create the bloc lazily, meaning create
    will get executed when the bloc is looked up via
    BlocProvider.of(context).

    Meaning that whenever you do declare a BlocProvider widget, all that happens is that the declaration of the create function that returns the bloc only gets saved in the memory, so either by declaring a nested one or a global one, the same memory resource will get taken, when you make a lookup for that bloc for the first time, the saved bloc will be initialized, here time complexity of the lookup operation will depend on the size of the widget tree, the BlocProvider will look up every single widget in the tree until it finds the right cubit/bloc, so here using a global BlocProvider in the main.dart will lead to taking more time finding it than a bloc/cubit that is being passed across screens with a BlocProvider.value.

    But here you need to ask yourself, does look up for the cubit/bloc only one time and use as many times as you want in the app worth it than making a new short look-up every time the widget sub-tree is inserted/removed from the widget tree.

    Login or Signup to reply.
    • If the program is designed by me, I will set Auth Cubit as the global state
    • Shopping-related states such as Category Cart Orders are merged into one Cubit, and it is decided whether to initialize once on the entry page or set it as a global state according to needs
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search