Flutter Firebase & DDD Course [15] - Note Watcher & Actor Blocs

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
with the notes domain layer fully finished and having the I note repository interface ready we can finally jump into the application layer to implement a few node blocks those will be responsible for loading all the notes and performing actions with notes such as deletion hello welcome to reso coder where you are getting prepared for real 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 in demand flutter developers in this 15th part of the domain driven design flutter series where we are building this kind of a note-taking app we're going to go into the application layer of the notes feature we're going to implement two blocks and those are going to be called note water block and then also note actor block why are there going to be multiple blocks for the notes feature actually those two are not all the blocks that there will be there will be one more block the note form block but they will come later on so why are there going to be multiple blocks right well the thing with blocks is that while they are very easy to work with when it comes to representing a certain state you can easily organize the states in your head as you are building them and it really provides a nice clean code the thing is that it turns out they're combining something like loading notes from firestore and then acting on a note like for example when we long press on a note we want to be able to delete it combining those two things so loading and deleting for example it's quite hard to perform from just a single block if you want to keep your states and events in check if you want to keep them clean so that's why the watching of notes either completed or only uncompleted and then what I call acting on those notes so for example deleting notes those two functionalities are going to be performed from separate blocks they are all going to call methods on the single I note repository which has the delete method as it has the watch all what uncompleted and then create an update methods so I know repository is only a single one but the blocks we are going to have multiple of them so let's go now into the application folder for the application layer and we are going to create a new folder which is going to be called notes and this notes folder will hold all of the different blocks which are associated with the notes feature so now it means that we want to have here the note water and also note actor blocks so let's right click on the notes folder we're going to say block new blog using the vs Co extension and let's call this one note water with underscore we don't want to use equatable because we are using freeze and it's going to create something called block inside the notes folder we want to rename this block folder to say note watcher and now before we get into the nitty gritty details let's also create another folder here containing a block this one is going to be called note actor that will be responsible for for performing the deletion of a note notes actor no we do not want to use equatable again and as we've seen before let's rename this to note actor okay we are going to first focus on the note watcher block and then we are going to come over to implement note actor and also as always you can get the code from the link in the video description to check it out at your own pace I always like to start implementing blocks by modeling their states first because state is something incredibly important when it comes to blocks this is what gives the block actual meaning all of the other things are just like the implementation details but states are the main thing which the block operates with so again we do not want to use simple classes for states we instead want to use priests unions so while we are at it let's also run the build command it will be available from the video description also so floripa brambilla run watch delete conflicting outputs you know the drill so while this is running we are going to create an F Union let's call it note water state which I have just copied from the previously generated class by the extension and now we want to provide the first Union case for the state which is going to be initial let's give it an underscore here and this is nothing too extraordinary initial state is almost always present this just means that nothing has happened yet no event has arrived into the block just yet let's also come over to note water block and add the PDF statements apart no water block that free stun dart so that we have some sort of a location for the generated code for the events and for the states which are going to be freezed unions let's also repair this failing line by saying nodes water state in initial and of course let's make it constant also and that's about it for the block for now let's come back to the state and actually let me also hi the frist freezed files so I have changed the extensions which I use for hiding generated files now I use something called hidden something Explorer exclude this one so check it out if you are interested the previous one which I have shown you a few episodes back just doesn't work very reliably it sometimes doesn't hide the files so if you have a lot of generated files and you probably do unfortunately with the current state of unions and data classes in dart then you may be interested in Explorer is excluded so to make the files hidden I will just go down here in vs code take priest G and get heap files ok and yeah now they're hidden cool so with the state what are going to be the additional states well they are just going to be load in progress this is for the time while we are waiting for the communication with fire store and we are going to show the expected circular progress indicator let's give this a name loading progress okay and let's copy them down the next one will be at load success and also change the class name and the last one will be load failure of course failure all right so loading progress will not hold any value in itself it will just be by itself representing loading progress but for the success and failure states we do need to be able to put something into those states so the list of nodes or the actual node failure so in the case of blocks we do not represent success and failure with an either type like we do inside the inode repository so for example here from watch all we return a stream of either node failure or Katie lists holding note entities so this is called for repositories but for blocks for their state we want to break it down to be even simpler than the either type so instead of either we actually create our own Union as you can see so the success state will hold only the Katie list of nodes let's call it nodes and let's import Katie that dark and also note that our the entity and in the case of failure is just going to hold node failure let's call it note failure again and that's it we have just basically split the idle type into our own custom Union cases and as you can see the state of this block is absolutely simple and this is why we are splitting the blocks into multiple ones so we are going to have the note watcher block which we are just now building for only loading the notes from fire store and then a different block for deleting notes from fire store or performing other actions if there are any in your case in your app and by doing this as you can see our state's and blog logic will remain absolutely dead simple and that's what we want always we do not want to complicate things unnecessarily if we can instead split it up and make it much simpler that's basically the single responsibility principle in action as you can see it really works so now that we have the state let's go over to implement events events which we want to have for the note waterblock are going to be watch all started and watch uncompleted started because if you remember in the app we want to be able to watch all of the notes and also only the uncompleted notes and we have such methods even inside this I know the repository for watching all and watching uncompleted so let me copy the note water event name we're going to again create a freeze Union note water event the first one will be called watch All Star it let's also name the class accordingly all right let's make it private also now let's go below we're going to say watch uncompleted started and this should be it right well it's not going to be it we are going to see in just a bit why we need to create it another event but for now logically we could say that these two events are all there is to our note water event union so now we can go over to the note watcher block and start implementing it right so we want to mark this note water block as injectable so add injectable and this will allow us to inject the block or use get it to obtain the instance of the block rather but also this will allow us to inject other instances of classes to the block so we want to inject and I note repository in here so let's call it note repository and let's populate a constructor with it currently there is no actual instance which is going to get injected but once we implement the repository interface into a real actual class that class will get injected in here under its interface type now we want to implement map event to stay so just as we have done previously we are going to say yacht each and use our Union type event that map select all the nodes by hitting ctrl V or command D on Mac and we are going to say block event handler using the extension and you can always get this code from the link in the video description of course and I'm not sure why the the colouring of the brackets stopped working in this project for now I could just restart the Visual Studio code but I don't really want to do it but I guess I'll have to so I'll be right back okay so now with the highlighting of the brackets working we can get into implementing the watch all started event handler over here of course we want to first yield the loading State so load in progress notes watcher state hold in progress and let's also make it constant and as soon as we indicate that load is in progress we want to say note repository that watch all because we are inside watch all started and if this was not returning a stream but it would be instead of future which you may be more used to then we would just do something like await right away this put this into notes notes something right it doesn't work of course like this because it's a stream but if this were a future you would do this and then you would yield the notes watcher state load success or load failure depending on whether or not the notes is left or right of either right but the problem is that this is a stream this is not a future so we cannot just await it and yield it as simple as this what we need to do instead is for each and every event or element coming inside the stream we want to also yield a new state now I'm going to show you one way to do it which will work only if you have basically one event and you do not plan to switch between watching all of the notes and watching only the uncompleted notes and by implementing this the incorrect way we are basically going to have all the code ready for the correct way we're just going to copy it later so yeah the incorrect way is incorrect because the stream which we are about to yield yield each is never going to stop this will cause that any kind of an event saying that we should hate stop watching all of the notes and start watching only the uncompleted ones this event telling the block to switch what it's currently watching and yielding is not going to have any impact because of the way that streams and a synchronous generators in dart work that's sort of unfortunate and this will cause us to write much more boilerplate code then is necessarily should be needed right but let's go with this in the ideal world we should be able to yield each element coming from the stream where we are watching all of the notes but because of course we cannot just yield ace either note failure or KT list but we need to yield our own custom States load success or load failure we would not just yielded as simple as this to saying or repository watch all but we would also need to map the simple stream holding either into the custom Union cases so we would map each and every failure or nodes which is of type either node failure or catalyst node into failure or notes that fault and if we operate with the left side of either which means failure F we want to return note water state that nodes or load failure pass in the failure and if we operate with the right side of error which holds the list of nodes we will want to yield or return from this mapping function note water state that load success and passing the nodes right now we do have some errors I suspect that we are missing parentheses that's correct now let's put a comma here so that it's more nicely organized and we would call this a day yield each is pretty self-explanatory because we want to yield each and every thing which is coming through the watch all stream mapped into our own custom load failure or load success this would work perfectly fine for only one event if we for example had only watch all started this would be cool but the problem is that if we want to switch to watch uncompleted then we are now gonna be able to do that with the current approach the reason for that is that this yield each statement or however you want to call it is never going to stop emitting States that's because it's only going to stop when this original stream coming from the node repository is going to immediately done event in other words when the repositories watch all method is going to stop itself but that is never going to happen while we have the this screen this page open the stream will always be actively looking for changes and pushing the changes from firestore to us so it's never going to email the done event it's never going to be finished and therefore this guilt each contraption is going to for all intents and purposes we can call it an infinite yield loop if you want it this will cause that we are now going to be able to switch to only watching uncompleted notes so what can we do with this well we have to go with a different approach to mapping the incoming either of note failure or kettle is note into our note water states that approach will involve not yielding each but instead basically adding very redundant but needed event to the block let me show what I mean we are going to come to the node watcher event file again and in here let's create a new event which is going to be completely present here only for the sole reason of what I have just extensively described it will be called notes received let's also rename the class and it's going to accept an either note failure or Katy list note let's call it failure or notes okay so and again we probably need to rerun the build commands whoops ok let's rerun this so this event is going to really just be called from within the block and it will allow us to switch between watching all of the notes and only uncompleted notes because of the way that the yield each statement works that it's going to arrive in an infinite loop so to say otherwise so now we have another event we need to handle it which is the beauty of using the map function on our frist unions parameter nodes received is required so let's implement it as a block event handler and now from watch all started instead of yielding each and mapping the original stream to our States we're going to do something completely different we are instead going to listen to the original stream but leave the map in here for now we're going to listen was renamed the event parameter to notes and with each such notes or failures coming into our listen function we just simply want to add to the block a new event called note water events notes received and pass in the notes maybe let's rename the parameter to failure or notes to make it more in line with the other names which we have and yeah of course let's remove the yield each statement or yield each keyword from here and this should really work now before we go ahead and tweak it a little bit let's also put some code which is going to omit the proper States into the notes received event handler basically we want to just copy the code which was previously inside the map method so let's copy this failure notes that fold and we are instead going to put this into the notes received event handler and we are just going to use a simple yield keyword not ill each so yield event failure or notes that fold and we want to fold this thing which was previously inside the map function now it's here so we are folding and mapping the failure or right side of either to their respective states doing things like and this is going to allow for switching between watch all and watch uncompleted notes because we are not using the yield each keyword which is going to put us into an infinite loop basically here we are only listening and we can cancel the listening for all notes and instead start listening for only uncompleted notes very easily so how can we cancel listening to all notes to be able to switch to the uncompleted ones well to do that we need to store the stream subscription which is returned from the listen method we're going to store this stream subscription as a field inside the note water block it's going to be a mutable field stream subscription and it's going to hold the either note failure catalyst no let's copy that and let's call it note stream subscription okay now we want to add a subscription to this field whenever we call listen here so let's say note stream subscription equals whatever is returned from this listen thing and I know that this code looks horrible but what are we going to do with the dart formatter I mean yeah it's not pretty but it works that's the important part now to see the full meaning of why we have this note stream subscription let's actually start implementing the watch uncompleted started event handler so let's copy the watch allstar it code in to watch uncompleted and we are just going to change watch all to watch and complete it and that's it so why do we have this note stream subscription well because it will allow us to cancel listening to the previous stream so for example if the user decides to switch from watching all of the notes to only the uncompleted ones then what we want to do is insider watch uncompleted started to say that we want to note stream subscription that cancel and let's also await it as it's an asynchronous function so this way if we were previously listening and watching all of the notes over here now we're going to stop that and start watching on the uncompleted notes right now because by default initially the note stream subscription is null it's not signed we actually need to use the safe access operator so question mark and dot also called Elvis operator if I'm not mistaken and this way we are safe now all we need to do is for the user to be able to switch back to watching all of the notes let's copy this cancellation of the note stream subscription we're going to also do it from within watch all started now this block is like 99.9% fully implemented the last thing which we should do for a good practice and also for eliminating any possible memory leaks which in this case could result in unnecessarily observing data from firestore which would result in you being built for what you actually don't even see on the screen so that's not what we want to do and that's why we are going to implement the close method of the block close it's going to be overridden because block is in itself a stream so that's why it has the close method and in here we're going to say again a weight note stream subscription cancel and let's make this function async itself ok so that's it for the note watcher block where we looked at a very interesting caveat of why we cannot use the yield each statement or heel each keyword excuse me but we need to use the weird approach of having a separate event just for yielding our own states now we are going to implement the note actor block and this one will be a complete breeze it's now going to have any such KBS and it will be very quick to implement so let's go over there to note actor let's close off all of the note watcher classes and now inside note actors state again we are going to start with States we want to have a union for the state so let's say F Union Union note actor state let's import priest let's go into the note actor block right now and we're going to add the PTF statement also call and the first state again which we want to have here is initial just like in the note water state again even with an actor block which is going to be responsible for performing actions of course on the individual notes at first nothing is being done so this means the state is initial initial cool now let's go to the block and let's fix the error where we say no the actor state initial and let's make it constant this will be the initial state of the block and now let's implement or let's define all of the other states which can be present when it comes to acting on a note well it's going to be very similar to the water state on here the name we'll be a bit different instead of loading progress we're going to have action in progress because deleting something from a remote database is asynchronous so we want to be able to display some progress to the user so let's just copy this event multiple times down below and we're going to say action in progress call action in progress simple as that and the next one is again very similar to what we had in the watcher block this one is going to be delete failure because actually the only action we are going to be able to perform on a node at least when it's already created is that we can delete it so therefore we are going to have delete failure and then also delete success of course and let's also name the class is accordingly do it failure delete success with capital D and again failure should hold some sort of an instance of the failure so note failure note failure but in the case of delete success as opposed to the waterblock there is actually no data to represent success because we have deleted something right now so that means that data is no longer present and that's why we are now going to have any fields inside the delete success Union case alright now for the events because we have the state's fully done for the node actor block so events will be very simple there will be actually only one event and it's going to be the deleted event or delete event if you are not following the naming convention we have established so let's create a union again let's say note actor event delete it and delete it and of course we want to be able to pass in a note in their note notes just like that here we go because we don't have any other action to perform directly from the list of notes UI this note actor event is not even actually a union it's just a simple data class with a named constructor that's because it has only one constructor but we are going to call it a simple union because all the other events are unions but if you had a functionality where you could for example complete two dues right from the UI so if you clicked on it to do here you would be able to complete it right from over the notes list UI then you would have another event here called complete or to do complete it something like that and again it would be here inside the note actor event but the way we are going to implement the app we're going to be able to complete to do only from the notes editing form so we have only the deleted event over here and with this done we can now go over to the note actor block and implemented right it's going to be very simple to implement actually inside the map event to state we cannot even map the events you know as we do in the note water block we say yield each event out map that's because the event is a union but here because we have only one Union case this makes the note actor event into a data class not an actual Union so we cannot even map it to all of its possible Union cases so whenever a note actor event arrives into this man that we know that we are dealing with the delete event and that's why we can start yielding action in progress right from the bat so guilt cons notes actor bands or actually know the actor states excuse me it's going to be action in progress then we want to call note repository which we currently don't have so once again as usual added here final I know it's repository note repository let's add it to the constructor s final field and let's also mark this class as injectable call so we're going to call no repository that they'll lead this time and what do you want to delete well a note which is present inside the test in event so this one not event that note now this is an asynchronous method present in the on the repository so we want to await it and it returns something which we are interested in that a future of either a node failure or unit so let's store this value inside file possible failure it's equal to this and now we want to yield different states based on if a failure occurred or if everything went as smooth as butter so we're going to say yield and we want to fold the possible feature or possible failure fault and if there is a failure F we are going to return notes after states delete failure and populated with the f failure which is a note failure F and if everything is successful because it's just a unit there is no real data in the right side of either when it comes to deleting something from our store or from any other database which you use because again we are not being tied to file store the only layer where we are actually going to mention firestore is infrastructure but as you can see what we are building right now in this episode or even in the previous ones mostly is totally firestore free but anyway we just want to return delete success notes actors states do its success and it can be constant so let's make it constant shall we okay we are going to add a comma at the end so that it's nicely formatted and just like that we have implemented yet another blog which is the note actor blog and it did not even hurt so we have no director state no the actor event no the actor blog and also we have the note water state event and block where you could see a little caveat of how to work with streams and yielding something coming from a stream inside the block you need to create a custom event for that which is basically going to be used only from within the blog itself as always you can find the code written in this part of this tutorial series and the link in the video description and if you are serious about becoming a great flower developer who can build real apps for clients or at a job go to flutter that education link is also in the video description to get the top curated flora news and resources aimed at improving your app development career over there you can also subscribe to my mailing list to get the best for resources delivered quickly right into your inbox and if you don't want to miss more tutorials like this the next parts of this domain-driven design flutter series and also other tutorials about flutter be sure to subscribe to the channel and also join 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 an in-demand flutter developer if this video helped you with all that we have done with this weird yield each behavior and all that give this video a like and also share it with our developers who are surely going to find it beneficial to leave a comment if you have anything to say and see you in the next [Music]
Info
Channel: Reso Coder
Views: 5,948
Rating: undefined out of 5
Keywords: resocoder, tutorial, programming, code, programming tutorial, flutter, flutter tutorial, flutter firebase, flutter firestore, flutter firebase auth, flutter firestore tutorial, flutter firebase tutorial, flutter architecture, flutter architecture patterns, flutter domain driven design, flutter ddd, flutter database, flutter todo app, flutter todo app tutorial, flutter todo app firebase, flutter app tutorial, flutter app example, flutter clean architecture, flutter bloc
Id: rNDmfacXReQ
Channel Id: undefined
Length: 44min 27sec (2667 seconds)
Published: Wed Jun 17 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.