I been trying to understand how Riverpod works and was wondering how does it know when to destroy the state of a provider with the .autoDispose modifier when changing a route in Flutter. Is it somehow subscribed to the navigator changes?
The docs state:
A common use case is to destroy the state of a provider when it is no-longer used.
There are multiple reasons for doing so, such as:
- When using Firebase, to close the connection and avoid unnecessary cost.
- ***To reset the state when the user leaves a screen and re-enters it.****
The "autoDispose" logic doesn't depend on Flutter-specific logic.
Instead it relies purely on whether a provider is currently being listened or not.
When a route is poped, the associated widgets are destroyed. This causes the ConsumerWidgets in that route to stop listening to their "watched" providers.
Then, if a provider now has no more listener, it gets disposed.
Related
I'm new to using the Bloc pattern in Flutter, and I wish to update some widgets (i.e. state) for every bloc concerned by an external change.
For example, imagine that I have a trading application, and so I have a "Trading" component that receive some information updates.
My "Trading" component receive new information, but then how does it transmit the new information to the Bloc and so, how it emits (and update) the widget.
Any idea how I can do this? What is the correct pattern to follow ?
You need to emit the state changes (your trading data here) to your state using a BLoC / Cubit which will then rebuild the UI using BlocBuilder.
I know StateProvider is used for immutable states like counter value.But I couldn't understand StateNotifierProvider.Why and How I should StateNotifierProvider in my apps?
StateNotifierProvider is a good interface when a single state wants to be consumed for changes, and updated via method calls on its underlying notifier, encouraged to treat state as an immutable.
If your problem fits that, this provider is the best.
Some patterns call for a bit less rigor in updating the state, and for those a StateProvider can provide a read/write variable that still has notification wiring and the possibility of consuming other providers to give its value. A StateProvider still has an underlying notifier, but this notifier isn't subclassed with additional behavior as a StateNotifier would have been, enroute to the StateNotifierProvider.
If suddenly your state becomes more complex than true and false, you should use StateNotifierProvider. You can put methods in the StateNotifier class to handle your state. For example, adding or removing items from your state-List are two separate methods that you can no longer implement in StateProvider
What are the actual advantage(s) of Bloc over Cubit?
In addition to traceability (which you can also achieve with appropriate logging in Cubit), and advanced event transformations (I can't think of any "advanced" event transformations that Cubit can't do, since there is always a way to do it with Cubit. And if you're using clean architecture, domain/data layer can help with complex data manipulations).
Sharing and sourcing events
These are the things that I'm looking for that should be able to do with Bloc since these things can't be actually done with Cubit. However, it appears that these are impossible (or is it?) because adding event on a Bloc requires you to identify the actual Bloc where the event will be added. bloc.add(YourEvent()).
Also, event sharing is somewhat debatable because this can lead to a bad architecture/hard to maintain.
For event sourcing, I can't find in the docs if this is possible (reversing back to a specific past state?).
Am I missing something here?
As far as I know reversing to past state can be easily done when you have immutable states regardless of whether it is bloc or cubit. Having immutable states allows you to store list of states and restore whenever you need a specific state.
Bloc has no advantages over cubit but rather different purpose. In cubit you have action=>response (function=>states) whereas in bloc you have streams.
What cubit cannot do?
For example you can have two events being processed concurrently when using bloc (since bloc 7.20) but you cannot call two functions simultaneously on cubit.
Sharing events
You can share events implementation between different blocs because you have to specify what events bloc implements.
class MyBlocA extends Bloc<MyEvents, StatesA>
class MyBlocB extends Bloc<MyEvents, StatesB>
If I understood correctly, what you want to do is to process a single event in two different blocs, which you cannot do because event is emitted to a specific bloc. So it requires two calls:
blocA.add(EventA);
blocB.add(EventA);
Depending on your case you might listen to state of MyBlocA inside MyBlocB. This way whenever event for MyblocB appears, the action would depend on the state of MyBlocA.
Blocs and Cubits are same in terms of state management with only one difference of state mutation: Bloc is event driven and Cubit is method driven.
Apart from all of this, in terms of architecture not much is different as of now. All others have been mentioned precisely by #chris in the above. It is up to the developer on how to maintain the state in a way is manageable for us.
aren't events for dependency injection?
Cubit
call Action
set State
Bloc
trigger Event (inject something, depending on screen/page it was trigger from. as Example)
then call Action
and set State
I have my navigator setup and everything is working as expected, but I have a widget buried in my widget tree that needs to know about route changes and I can't figure out how to subscribe to them.
You could use the name of the route, accessible anywhere:
ModalRoute.of(context).settings.name
and listen to the changes of that value.
But generally speaking, if you want to listen to some variable changes deep in the widget tree, you should look at some state management options.
Provider, Bloc or MobX are some options.
flutter documentation on state management
I'm working with the flutter_bloc library. Imagine the situation, that you are navigating deep in your app and every screen on the navigationstack presents data (slightly differnet because otherwise it wouldn't make sense), that can be modified by the user. Because we are using Bloc, every screen is connected to it's own bloc. Now, the user modifies the data.
My question: How can I tell the other Blocs/screens to rebuild with the updated data?
To my understanding, the blocs on the routes which I'm not currently viewing, get closed. So they don't listen to events anymore.
EDIT: This assumption is wrong, see answer.
Final answer. My assumption was wrong. Blocs don't get closed, if the route is still on the navigation stack. So you can still add events to Blocs, which are on other routes.