Why should I use Provider in Mobx Flutter? - flutter

The official Mobx documentation for Flutter says that in order to transfer data correctly, you must use a Provider and refer to the context to retrieve the data.
But why can't I just call the Mobx class at the root of the application and access the global variable to get the data?
CbtStore cbt = CbtStore();
void main() async {
runApp(const MyApp());
}
Why should I be doing this?
void main() async {
runApp(MultiProvider(
providers: [
Provider<CbtStore>(create: (_) => CbtStore()),
],
child: MyApp()));
}
And how do I refer to Mobx inside the widget methods in that case, for example, if I want to call the action in the Mobx class in initState method? Now I do it in the following way. But when using Provider in initState there is no context.
#override
void initState() {
cbt.init();
super.initState();
}

Provider is used only for dependency injection with mobx. It is not used for state changes.
Now when you are using mobx you don't need a stateful widget in most cases because you are handling your state changes inside your mobx store and if there is any changes in the state we use Observer to change ui.
if want something to initialise with the screen than prefer using constructor of mobx class rather then initState.
for example,
class MyStore = _MyStore with _$MyStore;
abstract class _MyStore with Store {
_MyStore(){
getData();
}
}
Now don't use global providers for your all of store. Only Initialise a provider whenever you need it. So when you push a route wrap it with a provider so that Provider.of(context); can find it. Only use global store if it required globally.
You mentioned creating an instance of store to use it. When you initialise a store in stateless widget it, the data will get destroyed when you close the screen and when you reopen it everything will start all over again. It is useful when you don't need to maintain state after screen pops. It will based on your use case.

You should do what works best for your use case.
The reason why providers are useful is that they can be provided where needed. This could be in the application root, but also somewhere deeper in the widget tree.
Another advantage of the providers is that you can have a provider that notifies listeners. Widgets will rebuild automatically in this case, which can be useful if you have stored and need data to update everywhere in the application.
The initState does indeed not allow the use of providers directly. There are 3 solutions for this:
Don't have the provider listing (Provider.of(context, listen: false); This allows you to use the methods, but not listen to changes.
Use the provider in the build method, using the consumer.
I am by no means an expert on flutter, but this is just what I have experienced so far.

Related

Flutter: What is the life cycle of Provider state management?

Like in GetX, we have onInit(), onReady(), onClose() methods inside GetxController.
but in provider which extends ChangeNotifier doesn't have those methods.
so basically i have to use stateful widgets for init's and for other initializations.
So just wanted to know exactly the states of Provider.
Provider does not work as Gets Work. It uses flutter state life cycle.
you can understand like that:
Initialise provider at Starting of App
Create a class which extends Change Notifier
To fetch value- create instance of provider or use Consumer at You Widget
For Better understanding you can follow this Link:https://github.com/Code-With-Patel/Provider.git

Flutter bloc with calling api on an interval

I'm working on an app that accesses two api's that contain location data that updates regularly (every 5 seconds or so). I want to utilize flutter and flutter_bloc to manage my state, but I'm not sure where the interval would come into play. I understand bloc and how the ui interacts with it with BlocBuilder and BlocProvider, as well as providing a repository that handles the api calls. What I'm not sure about is where to put the interval/timer. My idea was to do a normal bloc setup:
class DataBloc extends Bloc<DataEvent, DataState> {
//constructor
#override
Stream<DataState> mapEventToState(DataEvent event) async* {
if (event is FetchData) {
var data = repository.getData();
yield* _mapFetchDataToState(data);
}
}
}
In the ui:
class MainPage extends StatelessWidget {
#override
Widget build(BuildContext context) {
final dataBloc = BlocProvider.of<DataBloc>(context);
Timer.periodic(fiveSeconds, (Timer t) => dataBloc.add(FetchData()));
return ui stuff
}
}
But I'm not sure if this is the right way to leverage BLoCs and/or timers. But I basically need to call the api on an interval and then have the data update in my ui without a full refresh of all the widgets. They're going to be icons on a google map, and I want the icons to update their locations when the data I pull is updated. How can I accomplish this? For reference, I've looked at the flutter_bloc docs for the timer app here and I thought it was a little overkill and that my idea above was simpler, just not sure if this is the right way. I'm pretty new to flutter so any help would be appreciated.
I'd recomend not to put initializing code inside build. Make it a StatefulWidget and add a dispose method to clear the timer. And inside initState setup the timer.
There's no right way in programming. There are best practices, so as long as it work for your use case is ok.
I would either put the timer into the bloc/cubit because its part of your logic and not of your ui.
Or if you use a repository I would probably use a stream listen to it in your bloc and periodically update the stream in your repo.
But any better suggestions are more than welcome, because I am also looking for some kind of 'the way to do'...

Notification to adjacent widget

I have a widget that contains a "save" button. After pressing that button several other widgets (not only ancestor ones) must save its state to the file. I don't know how to inform them. What is the best way to achieve that in flutter? I was thinking about using Notification in the "save" widget, closest shared ancestor would contain a NotificationListener that triggers an event to which every widget will subscribe. For me, it doesn't look like a solution.
Provider is the recommended way to do State Management for apps of all sizes. -–Chris Sells – Product Manager, Flutter. June 19, 2019
It's pretty complicated at first, best to check out Simple app state management
The ChangeNotifier uses the notifyListeners function whenever there is any change in the class:
class ChangeNotifierModel extends ChangeNotifier {
String stringThatChanges = 'startValue';
void changeTheString(String value) {
stringThatChanges = value;
notifyListeners();
}
}
The only code that is specific to ChangeNotifier is the call to notifyListeners(). Call this method any time the model changes in a way that might change your app’s UI.
I'm pretty new to Flutter myself, but the way I understand it so, it kinda acts like a wrapper, e.g. wrapping the child of main.dart
MultiProvider(
providers: [
ChangeNotifierProvider(create: (_) => SingleNotifier())
],
child: MyApp(),
));
don't forget the dependencies
dependencies:
provider: ^4.3.2+2

How do I implement a version of Flutter's WidgetsBindingObserver without using state?

I am building a flutter app and I need to call a method in a provider when the app goes into background.
I can easily do this by creating a Stateful Widget using the WidgetsBindingObserver (like the example here).
Is there a way to do this without needing a Stateful Widget? Provider is a great architecture and state is an anti-pattern.
Possibly, You could try creating a class that isn't a widget and extending WidgetsBindingObserver.
Something like this perhaps
class MyListener extends WidgetsBindingObserver {
MyListener({this.providerInstance}){
WidgetsBinding.instance.addObserver(this);
};
MyProvider providerInstance;
#override
void didChangeAppLifecycleState(AppLifecycleState state) {
providerInstance.doSomethingWithState(state)
}
}
Then implement the listener say in main() or yourApp() where ever your Provider setup is.
Thing is, there really isn't any issue with having a stateful widget at the root of your app somewhere as in the example. I honestly don't think your Anti pattern argument holds any relevance. Its common practice in flutter to have statefull and not statefull widgets.
By not having the statefull widget your just having to keep the state somewhere else, i.e. where ever it is your configuring your providers.

Flutter - Is it possible to use BLoC without provider?

class App extends StatefulWidget {
....
return HomeProvider(
homeBloc: HomeBloc(),
child: MaterialApp(
home: HomeScreen(),
),
);
class HomeScreen extends StatefulWidget {
HomeBloc homeBloc = HomeBloc();
}
From the above two scenarios, Most of the tutorials I read, is using the first option. Is the second method completely wrong? or does it have any negative effects in-app?
I can see one difference.
I can access the homeBloc by HomeProvider.of context in the first method. For the second method, I have to pass homeBloc in all the widgets.
Sure, you can use bloc without a provider. But if you share 2 screens with the same bloc, the stream value inside the bloc will be different, because you don't use the InheritedWidget (usually in a provider). The function of a provider is to provide your bloc with InhteritedWidget, so that multiple screens could access to the same stream.
It is definitely possible. I using a single bloc for my entire application right now (as I have come from react-native redux, apollo background, single source of truth makes more sense for me). An example is like below. You can declare your single instance of bloc and import it wherever you use it so you refer to same instance.
class Bloc {
/// Your Bloc Stuff
}
final bloc = Bloc();