Flutter MobX Tutorial – Transparent & Reactive State Management?

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
not a day goes by without a heated debate taking place somewhere in the comments about the best state management solution and mob X is one of them originating in the JavaScript world it has found a way to dart and unlike most of the other state management libraries mob X heavily relies on code generation which will allow you to write really powerful yet almost boil plate free code [Music] hello welcome to resew coder where you are getting prepared for real app development so that you will get freelance clients or a job and be confident about the apps you built so subscribe and hit the bell to join us on our quest for becoming searched after developers in this tutorial we are going to continue in a bit of a tradition here on reso Koehler in that we demonstrate state management libraries and solutions on an app which is simple yet real enough that you can really grasp the concepts we are now going to be building a counter app because that's what probably everyone is already fed up with instead we are going to build a simple weather forecast app where you can input a city search for it you have a probability that you will get an error as we did now which is simulating that the device doesn't have an internet connection and also you can get the actual generated fake weather we have already built this app in blocks so if you wanna learn more about how to implement this app with that state management solution check out the tutorial from the cart in the corner and in this tutorial you are going to learn how to implement this app with mob X and also not to bore you with creating all of the other stuff which this app needs for example the weather model which holds the city name and the temperature in Celsius or for example the fake where a repository which really just simulates a network delay and then generate some random temperature and outputs it in a weather model object so in order not to bore you with this and also with creating the basic UI like the loading indicator and so on you can get the starter project from the link in the video description and apart from it over there you can also go through the written tutorial where you will also find all of the code written in this video links to the libraries and over all go through this lesson at your own pace so let's just get started now and the first step is to of course and the dependencies to the pub spec dot yamo file and make sure that you add the same dependency versions because if you want to follow along with this tutorial the future versions of these packages can have some breaking changes possibly I don't think so but it can happen so really just make sure that you are on the same page with the version numbers for regular dependencies we are going to add mom backs flutter mob ex and also provider so that we can provide it down the widget tree and for dev dependencies we are going to add built Runner and also mob ex called gen so let's just align it properly and you can also copy all of this from the written tutorial so let's just save it to get the dependencies downloaded to our project and with that let's go over the principles of mob ex so that you understand how it works believe it or not a simple change notifier is the closest match to how mob ex operates really just a bunch of fields are stored inside a class which in the case of mob X is called a store and in the case of change notifier it is called change notifier of course and the values held inside the fields are collectively known as the state and those fields are then mutated which means that their value changes right inside the class called store this is unlike with state management patterns like block or redux which instead of mutating state inside class they emit new state objects if you don't know what I'm talking about that's cool just check out my block tutorial if you are interested in becoming familiar with the block pattern just know that mob X has none of that it really operates more like a change notifier what's different from the change notifier which is really the simplest state management solution out there for flutter if you do not count stateful widgets of course is that mob X brings in a bit more structure into how you manage state for example fields which are mutated are marked with add observable annotation then you can run some logic within the store class when an observables value changes and you can put the result inside the property marked compute it and then when you want to trigger some logic inside the store class from for example the user interface when a user presses a button you can do so with a method call just like usual but you have to annotate that method with add action annotation to be successful in mutating the state so we really have actions observables and then computed observables and finally reactions which we're going to get to in just a bit and really just hearing about this may not be the clearest thing for you and I completely understand that and that's precisely why we are gonna build a real app in this tutorial so let's get right to it and also you can go over what I just said in the written tutorial at your own pace so let's create a mob X store shall we we're gonna put it inside a lit folder in a new subfolder called state and let's create a new file call it whether stored a dart and inside of it we are going to use a nifty code snippet which I have made its trigger is MS so we'll just run that say weather and you can get this code snippet from the in the video description from the written tutorial there are a bunch of errors because we have not yet around the code generation but let's first go over what we can see here we are importing mob eggs of course then we provide a part statement for the generated file and then we have a class whether store which extends underscore whether stores of this package private class which is below here defined as an abstract class the public whether store class will be mixed in with whether store makes and this is going to be generated and if you want to learn more about how mixings work in the arts check out the tutorial from the cart in the corner and lastly we have this private whether store class which is actually where our custom code will go over here and this is mixed in with a store mix in which really does nothing it just indicates that this is what holds our observables computed observables and actions to the cogeneration library and you may also see something like this when you check out some aroma box code instead of extends you can see equals and instead of these parentheses or curly braces you can see a semicolon this is the same thing just a different syntax in dart if you do not need to have anything inside the class body you can also create a class like this however we are going to leave it at extends and these curly braces at the end now let's just kick off cogeneration with the flutter developers most favorite command which is flutter packages pub round build runner watch and you can either type it out manually into the terminal or you can also just hit control shift B and you can now select the task to run so we're going to select the watch task and after some time we're going to be presented with whether store dot G da dart file generated for us alright cool all of the errors are gone and we have the generated file right over here currently it doesn't hold anything inside of it but that will change as soon as we start adding some fields and observables and all of that stuff into our weather store but before that let's talk about the weather repository because we need to depend on that in order to call its method called fetch weather because otherwise we are not gonna be able to just get the weather from the fake API which we are supposedly calling here so to do that we need to have an instance of this weather repository right over in the weather store so how can we do that well we could just create final weather repository whether you close it or e and let's actually make it package private and just set it equal to be an instance of the fake weather repository we could do that but I'm going to show you how to do it properly of course when you want to do some dependency injection and I recommend always to do dependency injection through the constructor and in the written tutorial there is a link to a debate debating why it's really better to have constructor dependency injection and not field dependency injection because you may see some people do something like get it and inject dependency right into the field but that's not really great instead what you want to do for it to be more transparent is to create a constructor here so create constructor for final fields I just hit ctrl + dot and that's it and now inside whether store you can again hit ctrl + dot and create constructor - super now let's get to observable fields because that's the core of mob X without them you would not be able to react to state changes from the UI and we surely want to be able to observe better instance and weather is just this simple model class here and we also an observed a possible error message so let's end those two observables right over here we are going to have a wetter weather and also string error message and we're going to mark all of these fields with add observable and also the upper one will be an observable and had we been working with synchronous code this would be completely enough however because we work with asynchronous API is mostly we can not just store a simple weather over here we really need to let the UI know if the weather is already load did or if it's just loading this is because we want to display a circular progress indicator to the user like you can see here right we want to display this circular progress indicator and for that we need another observable field mob X comes with a class called observable future which is just a wrapper around regular future which is negative to Dart so let's just create another observable it will be of ty observable future holding a wetter instance and let's just call it weather future and notice that this is actually a private field now you may be asking like this future holds an instance of weather so why do we then have this separate weather object as an observable here couldn't we just remove this and leave it up to the future to deliver the weather instance over to the UI so that we can display this nice thing to the user we could do that but I think there is a much better option and that is to really just separate out the future and the payload of the future in this case the weather and instead of letting the UI work directly with this observable future which can be either pending fulfilled or rejected as you can see right over here if we go into the observable future you can see that the future status can be either pending rejected or fulfilled and instead of letting UI work with these enum values and just really get entangled with mob X we're going to introduce a bit of a separation in between the UI and mob X and create our own store state enum so let's create it right now any num store State which will tell the UI if this store holding the weather is currently in initial state or if it's loading or if it's already loaded this is something you may be already used to if you are using change notifier for state management and over there you would usually create a regular field so in the case of mob X that field would be also absorb all of type stores State and I'll just call it state let's mark it with observable because we are doing mob X and you would then update this observable field manually from within some method to indicate in which state the store currently is but because we are using mod X and we have this observable future over here we don't need to set store state manually instead we can make it a computed observable and make it into getter property and now we can run some logic inside of it and update this state field which is computed observable whenever the status of the weather future changes for example from pending fulfilled or to reject it and so on to kick out the update of this computed property we do not need to do anything special all that's needed is to have some sort of an observable property mentioned inside the state property and whenever this observable property for example where future changes its value this computed properties logic will kick off so really there is zero setup here all you need to do is to just use the observable field and automatically this computed property will be triggered how are we going to set the state of the whole whether store based on whether future well we first need to check if it's not null because if it is no and this is by default because we are not initializing it here so it's no whenever the whether store is first created or also if the where futures status so status is equal to future status or status or however you want to pronounce it so futures status is rejected in these two cases we want to set the state to be initial so return state dot initial or is actually called store State if we check out the finished app this is precisely what is done because when we have an error we just display this enter a city input this is the initial State and this input field is also displayed on its own whenever the app is first launched so whenever the weather future is no and then otherwise we want to return and let's use a ternary operator here instead of an if-else statement so if we're future that status is future status that ending in this case we want to display the loading indicator so we are going to output star state that loading and of course otherwise we are going to display star state that load date let's save that it's going to be nicely formatted and of course this should be load it not loading let's go over this one more time so when whether future is uninitialized or it's rejected so there is some kind of an error we display the initial State otherwise when the future is pending we want to display the loading indicator and then lastly the last option here is to display the actual loaded wear forecast so we set the store state to be loaded and remember that this weather future is here just because of this computed state property we are not going to access this weather future from the UI instead we are going to access state from the UI and then get the weather instance from this where observable not from the weather future observable future again you can do it differently but this is what I found to be working the best lastly we need to add some sort of a method for the UI to call whenever a city name is submitted and if you are familiar with change notifier you know that whenever you want to mutate state you need to call notify listeners or even from a regular stateful widget you need to call set state to really update the state and with mob X this is no different but instead of you manually deciding when to call notify listeners you just annotate a method with add action annotation and this basically does something like calling notify listeners for you automatically so let's create this method it's going to be called get weather and because it's going to be asynchronous let's make it richer in the future it's going to accept the string of city name its sink and over here the first thing we want to have here is a try-catch block and whether repository can throw a network error so let's just catch this single error so instead of catch we're going to say on network error and also if you are interested in knowing how to handle errors properly in your flutter projects check out the tutorial from the cart in the corner over here we are doing it in a more simplistic way because I do not wanna bug you down with anything which is not mob X inside the try clause let's first reset the error message to be no this is because of course error message can be set to something already from the previous call to get wetter so we just wanna make sure that error message is nicely reset every time a new weather is trying to be fetched so let's set it to no now we want to call the weather repositories method more precisely the fetch water method and pass in the city name if we take a look and as we can see it returns the future holding a wetter now usually you would await this directly and put it inside for example this weather observer right so we're equals await where a repository fetch weather but if we did it like this we would need to really update the state manually so state is equal to store state that low did right of course we currently cannot do that because state is a get only property but let's imagine it's just a regular field you would need to put here state is equal to loading and whenever an error happens you would need to set it to be initial state is equal to store state initial and then you would also need to set of the state to be initial by default like you can imagine that hopefully but because we are using an observable weather future we do not need to do that after all we have made this state field or property to be a computed observable so it will do this setting of its state for us all we need to do really is your first of course the leads all of this non-functional code and now instead of putting this future directly into the weather observable holding just this simple weather we are instead going to wrap this future gotten from the repository into the observable future where a future so let's set this equal to this and this seems to work but it will not work precisely so we need to wrap this inside an observable future and with that we have just made it possible for the state to be computed whenever the status of the weather future changes and again observe a future really just extends or implements actually a regular future so you can work with them really nicely together for example you can await an observable future just like you can await a regular future so let's do it now we're going to await the weather future so let's go over this one more time we set error message to know so that we get rid of a possible previous error message and then we wrap the future gotten from the weather repository which is just a regular future inside an observable future and put it inside the weather future field then we await until the completion of this future and when this future finishes so it's fulfilled apart from this awaiting being finished and the result of the future being put into the weather observable what also happens is that the futures status comes from pending to fulfilled and these triggers this computed property here which will be set from loading to load it and of course when there is an error we are going to set the store state to initial finally inside this catch clause we are going to set the error message to be equal to good and fetch where is the device online and that's really all there is to the whether store I know this may have been tough to understand so you can always go through the code and through the written description of what we have just done in the written tutorial to which you can get from the link in the video description having this whether store implemented there is nothing more for us to do than to start working with the user interface first let's go over to main that dart because we want to provide the weather store over to our UI more precisely to the weather search page so let's wrap this with a provider widget let's import provider and we are going to specify a create method which will grant us context which we don't really need and we're going to instantiate whether store over here and pass in the proper instance of the weather repository which in this case is its implementer fake whether it Pastore now we can have over to weather search page and we have most of the code already implemented because really there is the scaffold and individual states already pre-built so for example when the state is initial we're gonna show initial input when it's loading we're going to show the progress indicator and then when we have the weather model instance we will display it inside a column and all of that nice stuff and finally we have a city input field for which we need to implement what's gonna happen when the search button on the keyboard is pressed but let's go first from the top down we will want to store the whether store instance inside a field you will see why in just a bit so let's just first create whether store field it will be private where store and in order to get this whether store using provider right here we need to override date change dependencies method and here we are going to set whether store whenever it's not null to be equal to provider that off if we first import it so of whether store and as in the context and also import whether store alright the reason we are overriding the change dependencies and not in its state is that in in its state you just cannot get anything using provider from an ancestor widget you really have to use the change dependencies instead of in it state method and this operator will make sure that the whether store will be set to whatever it is governed from the provider only if the whether store field is currently null otherwise it's not going to be reset so why did we put this whether store into field why are we not just calling provider off where a store from within the build method itself that's because we wanna show a snack bar and for it we need to create a reaction reactions are a way to trigger a function whenever an observable is updated and they are used mostly from the UI to perform some side effect for example showing a snack bar as we are gonna do in this tutorial or maybe showing an alert dialog or something like that although you can also have reactions do some other stuff but mostly this is what you will see there is some UI related side effect and while there are multiple kinds of reactions you can check them out from the official Docs linked in the written tutorial we are going to use a simple reaction called reaction there is also auto run and when and all of that but for us reaction is all we need here reaction can be created simply by calling reaction which needs to get a predicate and also an effect the predicate will tell which observable you want to observe in the reaction so we are going to say that we want to observe an observable from whether store and more precisely it's going to be the error message because whenever an error message is updated we want to show a snag bar showing on the snack bar will be done in the effect method which will accept string message simply because the error message is of type string and how can we show a snag bar when a snail bar needs to be shown on a scaffold but we cannot just call scaffold of context and just show snag bar right over here just like that we cannot do that because currently we are within the same widget as where the scaffold is defined because of it we need to create a global key for the scaffold State scaffold State and let's just call it scaffold key and let's set it equal to simple global key here and now we're going to provide the scaffold key to be the key of the scaffold so let's just define it really quickly and now instead of calling scaffold off and trying to find it in an ancestor widget we are instead going to use the scaffold key that current state to get hold of the state of the scaffold and on and we can now show snackbar just fine even though we are within the same widget and here we just simply want to instantiate a snag bar which will hold content and its text will be simply the message which in this case is the error message but the thing is that a reaction grants you a reaction disposal and when you are a decent developer and you see something like this poser you should be scared because you probably need to dispose of this otherwise you are going to get memory leaks and nasty stuff is going to happen maybe even you are going to get an app crash so how can we dispose of this reaction well we first need to store the reaction disposal which is returned from it and you could just store it inside reaction disposer field just like this right and store it directly in this disposer and then inside this pose you would call disposer that call because it's a callable class or you can also just call disposer end to parenthesis this would dispose of the reaction but you may have instances where you will have multiple reactions defined and you probably just don't want to have a bunch of disposer like disposer one disposer two and so on because that's really inefficient instead it's probably the best to put it inside a list of disposers so list of reaction disposer this buzzers and now instead of setting disposers equal to be the reaction output we are going to say disposers is equal but only when the disposers are not already set and it's going to be equal to a list of reactions cool so if you have multiple reactions you will add them all to the list of disposers like this but we have just one so that's also fine and now inside the dispose method you are going to call disposers that for each and for each disposer D we are going to call it with this we have the snack bar sorted out which is also need to update the UI widgets whenever the state changes so inside the build method we are going to get an observer over here which grants you a builder with a build context but we do not need any of that build context so we can just ignore it with an underscore and the observer widget works very much like the computed property inside the store so you do not need to tell which observable you are trying to observe you just need to mention it inside the observer and it's automatically going to track that observable whenever it updates so let's do just that we want to track the weather store state we're going to switch over it so switch case where a store that state we don't need the default clause and in case it's store state that initial we are going to return built initial input then in case its store state that load ding we are going to return built loading and lastly if the state is store state that load it we want to of course without the column here after case we want to return billed column with theta and TAS in a wear instance which is located nowhere else then in the whether stored under the name whether great so whenever the state changes we're going to run this observer which will rebuild the part of the UI and the last thing which we need to do is to call the action whenever a city name is submitted so the action on the store is just called get weather and invoking this is not different at all from just calling a regular method so let's just get hold of the weather store because we are inside a different widget we can now use the provider let's start inside final weather stored is equal to provider that off the type is whether store and once we have that we're going to call whether store that the action name so it is get wet and pass in the city name which is submitted from the text field and with this we can now run the app and as you can see we have the app prepared for users to use so let's get London again and we're going to get the temperature and also we can get an error hopefully it's going to occur yep we have an error and as you can see with the error we have just gotten the snack bar and then we can again get temperature again an error and again nice temperature is displayed and to go through this tutorial at your own pace once again and to get all of the code check out the written tutorial available from the link in the description so you have just built an app using mob x4 state management and everybody has different tastes and for me personally I really lean more toward the site of block because of its clean unidirectional and state machine like feel however if you want something with a light boil plate and you also want a step up from a simple change notifier then mob eggs may very well be your stay management package of choice for me it's not but I would still recommend it if you wanna step up your foster game up a notch from change notifier or really if you just do not enjoy working with block and its streams and all of that stuff which may turn some people away from it but hey everybody's different right and if you are serious about becoming a great flutter developer who can build real apps for clients or at the job go to flutter that education and link is also in the description to get the top curated flutter news and resources aimed at improving your app development career over there you can also subscribe to my mailing list to get the best photo resources delivered weekly right into your inbox and if you do not want to miss more tutorials like this be sure to subscribe to this channel and also join the notification squad by hitting the bell button to make sure you grow your flutter skills because here on reso coder I am determined to provide you with the best tutorials and resources so that you will become a searched after flutter developer if this video helps you give it a like and also share it with our developers who will surely find it beneficial to them to leave a comment if you have anything say and I see you in the next video [Music]
Info
Channel: Reso Coder
Views: 23,936
Rating: undefined out of 5
Keywords: resocoder, tutorial, programming, code, programming tutorial, flutter, flutter tutorial, flutter state management, flutter state management tutorial, flutter state management mobx, flutter mobx, flutter mobx provider, mobx dart, flutter mobx vs bloc, flutter provider
Id: 8j7W91ZJuV0
Channel Id: undefined
Length: 39min 13sec (2353 seconds)
Published: Thu Dec 26 2019
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.