What is the use of provider in flutter? - flutter

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

Related

Having a stateful service layer while using mobx

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

How to subscribe to Route changes in Navigator 2.0

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

ChangeNotifier wrap class around each instance of a model

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
}

Flutter BLoC: Are Cubits better then BLoC?

I'm working with Flutter quite a long time and have a bunch of released products. I never really liked BLoC and preferred to use Provider or later Riverpod.
I just don't understand that event concept. Why do we still need it? And i'm confused because of it's actual popularity... BLoC has Cubit subclass that seems to be more simple to use, but everyone just keep telling: "Cubit is simpler, but not so functional". But what are limitations?
I even think that Cubits are MORE USEFUL and MORE SIMPLE at the same time:
With Cubit you just call it's method with params. You still can listen its state AND get the method return value if needed too.
You don't need extra coding implementing these Event Types.
You don't need extra extra coding implementing how bloc will handle every single event type. METHODS DO THAT JUST FINE.
example:
User taps some product's "Add to cart" button.
Cubit:
cartCubit.addProduct(productId);
BLoC:
cartBloc.addEvent(UserAddsProductEvent(productId));
inside them:
Cubit:
void addProduct(String productId) async {
//some validation...
if(...){...}
final result = await cartRepo.addProduct(id);
if(result == ...) {
state = someState;
//....
}
BloC:
void addEvent(CartEvent event) {
if (event is UserAddsProductEvent) {
_addProduct(event.productId)
} else if (event is....) {
//.....
}
}
void _addProduct(String productId) async {
//some validation...
if(...){...}
final result = await cartRepo.addProduct(id);
if(result == ...) {
state = someState;
//....
}
What is the point?
There's a good overview of Cubit vs Bloc in the official documentation.
In short, Cubit's advantage is simplicity, while Bloc provides better traceability and advanced ReactiveX operations.
In our projects, we use both Cubit for simpler cases, and Bloc if the logic is more complicated and some "limitations" actually become useful:
You can emit a new state only as a reaction to an event, so the implementation is more straightforward (but more verbose as well).
All the events are processed one by one. Again, it makes implementation more reliable and easier to maintain.
Also, that can be a matter of personal preference, but I like Bloc for its close mapping to the FSM pattern. In most cases, the application state can be nicely represented as a state machine. It's easier to discuss the implementation even with a whiteboard, as you can just show the scheme with a number of states and events changing that state.
If you're happy with Cubit, then you probably don't need Bloc. After all, the main goal is to make the architecture easy to understand and to maintain.
BLoC
The advantage of having events instead of direct method calls is that you can debounce/throttle, buffer the stream before doing your logic.
In other words, you can use special methods applicable for events logic.
Cubit
If you start with Cubit for a new project, the idea why it exists is that later you will have the ability to migrate from Cubit to BLoC.
This means that if at the beginning of a project you think that BLoC is too much overhead and you need simpler state management (without events, boilerplate, etc.) you can choose cubit and migrate to BLoC with fewer efforts, than if you selected a different state management solution like MobX or Riverpod.
So with Cubit, you first implement the state and functions. Later if you decide to switch to BLoC you add events and EventHandler.
More you can read here (official docs): Cubit vs BLoC
Cubits are easy to understand and implement, while still being quite powerful. I wrote a few small to middle sized apps using cubits and hooks, so it's a matter of preference whether one chooses Blocs or Cubits or both.
You only need to be careful with the things that you emit in state, many times I saw developers (me included ;) being surprised that UI doesn't update. It was because the object/list was equal to the previous one, either becase equalTo() wasn't correctly implemented or the list size remained the same.
I actually wrote an extensive Flutter tutorial showing how to write a clean Flutter app with cubits and hooks.

Flutter is using provider to load data is the right option?

So i have a situation where i make an request from the server for one widget.
The widget is at the home page, lets take the worst case where the data is huge and the request take time.
Should i change the widget to stateless and make a provider which i will initialize before i run the app with all the initial data?
Should i contain all the data of the widgets at home page and deliver theme as props, i miss understood the concept of managing the state here, I'm coming from vue and i try to write my first app and I'm struggling how to structure my data through the routes.
I would like if some one explain or give a good source that show how to initialize data from third party
before the home page reload.
Which approach is better getting all the app data before the app reload or request data every time from db with cash
You might have seen this approach in other apps as well which is to show a splash screen until the data has been loaded and ready to be shown. This approach is mostly used by apps which got large data to load at the start. You could achieve this in your initState like the following.
#override
void initState() {
loadData();
splashTimer = Timer(Duration(seconds: 4), () {
_goToHome();
});
super.initState();
}
State management in flutter is a topic with hot debate, there is no best approach, but using one for sure is better than nothing. However there are exceptions to this, sometime adding a state management to a simple part of the app is not recommended. Regarding your case, it can be done without a full state management solution, by using a FutureBuilder for example. Or it can be also done with Provider, BloC, Redux...
As a naïve general rule, if the state is to be passed down the widget tree more than 1 or 2 levels, you should probably start looking for a state management solution depending on the use case. As I already have said, there is no one best state management solution.
Also, it is ok to use more than one as long as you know what you are doing but in general as a best practice it is not recommended to use more than one.
Regarding the second part of the question, it totally depends on the nature of the data and it's size. If the data is big and it is a small possibility that the user will be using all of it, it is better to load it on demand, also loading all the data upfront will increase the cost on the backend side.
However getting the data upfront, makes the experience more seamless to the user (Not waiting while using the app, but he will have to wait a little extra when the app is first loading).
So as you see it is a balance. Also it is good for the server and the app to do some type of caching since it helps reduce the work on the server side and decrease the bandwidth usage on the phone.
An example for caching images you can use Cached Network Image Link, example from flutter cookbook Link.