I am looking at using MobX for my flutter/dart application.
class MyWidget extends StatefulWidget
{
MyWidgetStore _store;
}
class MyWidgetStore extends Store
{
// Listens to the events of the service to then pass them on to the widget via MobX
ServiceLayerWithState _service;
}
class ServiceLayerWithState
{
// this service layer class will be used in multiple widgets
// Will send events when that state changes
}
The consensus on the internet seems that you write a store for the state of the application and share that store on multiple places.
Call me old fashioned, but I'm used to the MVVM model from C# and enjoy to have a Store (ViewModel) per widget instead.
Should I alter my view on where to store state and make all my services stateless? And instead put the state in the Store and share stores? Would there be a downside on the approach I am taking?
flutter is a flexible framework you do not need to stick to particular architecture while development.
Mobx provides you the functionality of observer and can solve most use cases than other counter-parts.
If the state needs to maintain across the pages, keep it in APP Level state (Mobx/Redux/Provider etc..) else for single page or widget use stateful widget and just setState is enough.
“The rule of thumb is: Do whatever is less awkward.”
Related
How do pass an instance of one Bloc instance to another bloc, so that we can use BlocA state change in BlocB
Well, technically just pass it as a parameter. But you shouldn't. It is not recommended by the author of Flutter Bloc.
The recommended solution is to let blocs communicate via either the presentation layer (the UI) by using BlocListeners, OR via streams from injected repositories.
There is a segment on this in the documentation:
https://bloclibrary.dev/#/architecture?id=bloc-to-bloc-communication
I have multiple model objects delivered by some data source in my Flutter app, each is identified by its ID (an integer field).
Each model and its state can be represented in multiple widget.
I'm making a bloc object for each model object (for example a model with ID of 3 shown in multiple widgets and they should share the same bloc instance).
From some of these widgets, I can send an event to the bloc instance, and have a new state, and of course, this state should be represented in all of the widgets that are sharing the bloc instance.
The scenario in my mind should be as follows when fetching the data:
1- Each model object fetched from some data source and is delivered to the presentation should search for its corresponding bloc instance.
2- If the bloc instance is created, use this bloc instance (and update its state if necessary).
3- If the bloc instance is not created, create one and use it.
My main problem is, I can't seem to be able to create those bloc instances globally, and access them in a "dependency injected" way. The dependency is the bloc instance and identified by the model ID.
I normally use get_it to register singleton instances, but now I need "Singleton instances uniquely identified by the model IDs"
Also, since blocs opens streams, these should be closed by hand since I think we can't use BlocProvider widgets in my case. If there is a solution to that, that would be much appreciated too.
I have an application where I display a list of cards that represent a model (Let's say a Person). These are stateless widgets as they cannot be changed directly. These instances are obtained from an API and, since the amount of items is large, I am using AutomaticKeepAliveClientMixin to keep them from reloading and triggering more API calls.
When clicked, these cards lead to the Person's page where there we can edit some information on them. Using a StatefullWidget here with setState takes care of all issues related to the page. However, when I pop the individual page the card that was clicked does not reflect the changes made.
I was thinking of writing a ChangeNotifier wrapper for each Person but from what I've read this is a bad idea. Using more powerful state management tools like BLoC or Redux seems like overkill too. How can I implement this properly?
I think you should try:
ontap: () async {
await Navigator.push ....);
ref
}
Well, I am sort of new to Flutter, My question is why we use providers in Flutter, I know it is used for state management. But I am looking to know the most common use case of providers.
You need to be able to move data between your Widgets. It's an easy way to do it.
You start your root Build method in the app with:
#override
Widget build(BuildContext context) {
return MultiProvider( // Multi means you can have more providers if you need
providers: [
ChangeNotifierProvider(builder: (context) => MyStateClass()),
],
child: MaterialApp(....
Now you can place all the data you need to share in the MyStateClass() and place underlying Widgets inside:
Consumer<MyStateClass>(builder: (context, state, child) {
// your code here - return(SomeOtherWidget());
})
or inside your Build methods:
#override
Widget build(BuildContext context) {
MyStateClass state = Provider.of<MyStateClass>(context);
// ... TODO ... return (Widget)
As you asked that why we use provider in flutter, so i will be providing only theoretical explanation which i think will surely help you to understand what
actually provider is and why it is used.
Suppose you are working on a large app with a lot of folders and files.
Now if the user have interacted with your app(say pressed a button or something like that) then the app have to build itself again to update to the changes that the user had made.But wait! this doesn't looks a good deal, to build the whole app again just to make changes in some particular section.
So, here comes the Provider to solve this problem.
A Provider is basically a container or a storage that stores and provides you with state or data.
Also, we know that widgets are arranged in an app like a tree like fashion.
so, if u assign Provider to any node in the tree then all the children of that node will have access to the data that is provided by the Provider.
Back the stage ,Provider comes with a listener and these listeners are assigned to the children of the widget to which Provider is attached.
So, If the user interferes with any widget that has a listener then the app will build only that particular (which the user interacted) widget again (not the whole app).
What is provider and how it's works ?
Provider is a simple way for state management, it works on the concept of PUB_SUB,
Which means there is one provider and multiple subscribers which is called consumers here. ex : youtube.
Whenever there is change, with NotifyChangeListener it will update all the consumers.
A wrapper around InheritedWidget to make them easier to use and more reusable.
By using provider instead of manually writing InheritedWidget, you get:
simplified allocation/disposal of resources lazy
loading a vastly reduced boilerplate over making a new class every
time devtools friendly
using Provider, the state of your application will be visible in the Flutter devtools a common way to consume these InheritedWidgets
I'm new into flutter and im using the provider package for state management and i have a typical scenario where messages are coming as event and handling this event is written in a separate class, as soon as a message arrives I have to update the message list which is defined in the provider class to which the other widgets are listening
Now how can I update the message list in the provider class from the class where the event occurs? (I cannot use provider.of(context) since it is a plain class and i don't have access to buildcontext )
I have tried creating a new class of the provider class and then updating the message list but for some reason, it is creating a different instance of the provider class
Provider is a dependency injection package that specifically uses the widget tree (i.e. the build context) to pass around instances of classes. If you don't have access to a build context, you can't get the instance.
Instead, you're going to want to use something like get_it or flutter_bloc for state management that doesn't require a build context. Alternatively, you could change the class emitting the events to be a singleton.