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.
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.