Flutter Bloc Tutorial For Beginners | BLoC Architecture/Pattern & State Management Explained

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
in this video we'll dive deep into the world of block by exploring the block State Management tool as well as the block pattern we'll start by adding State Management to the default counter app using both Cubit and block after getting a rough idea of both the tools we'll delve into cubits with a to-do list app and explore block further by adding form validation to a login form app finally we'll implement the blog pattern in the weather app by the end you'll have a clear understanding of Cubit block the block pattern and the package capabilities the prerequisite for this video is the basics of dot flutter and provider if you're not already familiar with it you can watch the 20 hour free tutorial present on the channel subscribe because the button lights up when I say it now let's get into the video so we're going to start off with the count app so what I'm going to do first is go to the lip folder go to the main do do file and first I want to remove all the comments so I can just press command F then I can doward SL sl. as RK then I can click on this particular icon which is use regular expression after that I can click over here which is toggle replay and then I can click on this button which will replace all the comments with an empty space after that I can just press command s which will format the entire document for me and now all the comments are out of my file the next thing I want to do is just take this homepage and put it in a separate file of its own so so I can just create a new file in homeor page. do then I can import material do. package and paste this code in so I have my homepage here now the final thing is just to import this homepage now I'm not going to edit any code inside of this right now we're not going to add any extra features or anything else to this counter app until we get to implementing the block section in the code so let's install block to install block let's go to Pub dodev and then we can search for the block package now when we search for the block package we we get two results that we might use block and flutter block the block package contains things that you will use in your block layer like the block class this isn't necessarily flutter dependent it is just the logic architecture of your app so in theory you can also use this particular package in your dot apps only flutter block on the other hand contains elements that you can use in your UI layer it includes widgets like block provider block Builder that you're going to get into that will make it easy for us to implement the block State Management and display the data on the screen and flutter block contains the block package so we don't have to worry about it either so we can just copy it and go to the the pope.l file in the dependencies I can just add the flutter block package after that is done we are all set to manage State using block now there are two approaches you can take while managing State and block the first approach is by using block State Management and the other one is by using Cubit now there are advantages and disadvantages to both of them we which we'll discuss in great detail but right now now I'm going to implement both of them in this counter app so that you get a rough idea of what's what the difference really is and then we'll dive deeper into each of them so right now first I'm just going to start off by creating a cupid folder first we'll Implement State management using Cubit so I've created my Cubit folder inside of it I'm going to create another file which is going to be called countercore Cubit do Dot and I like this naming convention because the first part of this name counter suggests what my state is going to be what state am I managing inside of this Cubit and underscore Cubit tells me that well it's a cubit it's not a block package like it's not using block over here it's using Cubit so that's pretty helpful for me as well I can click on enter and now the first thing we have to do over here is create a counter Cubit class but just creating a class isn't enough when we create a class well we've just created a class we cannot manage State inside of this class to get started with State management using Cubit we first need to extend it to Cubit which comes from the flutter block package so make sure you've imported this at the top and after that you can extend it which will give you another error and the error says that the super class Cubit Dynamic doesn't have a zero argument Constructor try declaring a zero argument Constructor in Cubit dynamic or declaring a Constructor in counter Cubit that explicitly invokes a Constructor in Cubit Dynamic what does this even mean it basically means that if we go to cubit's source code so I press command and click over here I'll go into the source code of Cubit do dot well basically the block package code and here I can see it is an abstract class which extends Block Base and it has a Constructor requirement and this is what the error is telling us if you H with this it says Cubit doesn't have a zero argument Constructor that means it has a Constructor and its value needs to be passed from the child class to the parent class so we need to pass in the value from counter Cubit to this Cubit and what is the value that we need to pass well it's mentioned over here we will have to pass in the initial state of our counter Cubit so we left with two questions after this the first question is what is our initial State going to be and what does initial State even mean in this context and the second question is how do we pass the initial state from the counter Cubit class to the Cubit class let's answer both of them so what are we managing over here we're managing the counter variable so whenever I click on this increment button it increments by one right this is the state that I'm managing over here so what is my initial state going to be well if I refresh my initial state is zero because whenever I refresh the app I want Z it like I want my counter to start from zero so that's what my initial state is whenever the Apper starts I want it to continue with zero and the second question is how do I pass the value from counter Cubit to Cubit to do that we can just create a Constructor we have counter Cubit over here and then we can use a CO in then call Super and then we can pass in the value and this is how the error is gone and we have passed the initial state to our Cubit class and this state can be literally anything you can pass in a class you can pass in string you can pass to it any data type you want so we have created a Constructor and then we're calling super which calls the super class which is the Cubit class and passes the value to its Constructor so now that this is created I just want to see the initial State showing up on my screen what I'm going to do is replace all of the State Management logic that's present in our code currently we'll replace that with block State Management and to be more specific I'm going to replace it with the Cubit logic so first of all I'm just going to remove the increment counter and counter variable I'm also going to remove this increment ment count of function call over here and just going to put an empty function we're going to change this later on but for now this is just fine we first want to display the initial State on the screen so let's figure out how to do that so what I can do over here is just create an instance of the counter Cubit class so I can just have let's say counter which is equal to counter Cubit and if I do that this would be an instance of the counter Cubit class and that's good but if I just put a full stop after this I get all of these options where are all these options coming from if I never implemented any of these attributes in my class well they're obviously coming from the Cubit if I just remove this call and just put it like this and come over here we wouldn't get any of those suggestions they're all coming from the Cubit class which helps us to manage the state so from all of these values the value that I need is state state would give me the value of counter and I can just take that and put it over here and with that I'm able to display the state of my app but there's one problem over here and that is this shows up as Dynamic counter and we know that we should refrain from using dynamic in our app so how can I make sure that this is given as int to do that we can just go to the counter Cubit class and over here we are extending to Cubit and we can just pass a generic type over here which is of the type int once we do that this counter would become the type of int and even over here if I just try to pass a string to my super class it wouldn't accept that because the argument type string cannot be assigned to the parameter type int since we've mentioned the type over here we've made our code a little better than before so we don't have to use Dynamic anymore and we know that the state of this Cubit class is going to be an integer and that's what we get now I can just restart the app and there it shows up it shows up zero it seems like nothing has changed but if I click on the increment button the value doesn't get updated and that's because I've not created any function that would increment the value of the counter Cubit State over here so I need to figure out a way to do that so I can just go to the counter Cubit class and inside of here I can create a function that would increment the value of the state and notify all the listeners that hey the value has been updated so I can just create a function over here which is called increment and now inside of this I just want to increment the value by one so I need to take the state and update it by one so if I just do state is equal to State + 1 it would work but this doesn't work because state is not a Setter it is not a variable that can be changed it is a getter a getter cannot be changed so I cannot use this and because of this another function is created which is emit emit updates the state to the provided State as you can see over here emit updates the state to the provided State what this means is emit updates the state of this class to the state that is provided in this parameter so if I just part image State + one it would update the state to state + one and it would notify all the listeners listening to this counter Cubit that hey the state has changed please update your UI so now that our increment function is done I can just go to the homepage and over here I can create an onpress which would be counter Cubit so I can just take counter cubit do increment and if I just do this I should hope that it starts working right however when I click over here the state doesn't get updated what's the problem to understand the difference I can just print over here before and then I can just pass in the state over here and I can just say after so here I'm just checking before the emit is called what is the State and after emit is called what is the state if the state changes that means the increment function is called correctly the state is being updated properly there's problem somewhere else so I can just restart my app I can click on the increment button and I can open my terminal to see that before it is zero and after it is one so the problem isn't in our Cubit it's all good I can just remove this again I can close my counter cubit so what could the problem be the issue is that I've created two instances of counter Cubit over here so what's happening is I'm creating one instance of counter Cubit I'm creating another instance of counter Cubit and in one instance I'm calling the increment function and its state is updating by one so the state over here becomes one but the state on the other Cubit is still zero which I'm using to display on the screen so this zero is being displayed on the screen instead of this being displayed so I need to eliminate the usage of two cubits I just need to use one cubit to handle this so what I can do is just create something known as counter Cubit over here which will hold the instance of counter Cubit class and then just call it final counter is equal to counter Cubit dot State and we get an error over here and the error is there because we cannot access counter cubit in an initializer over here so I can just take this from here and put it over here right that should be fine and then I can go down and I can use the same counter Cubit to increment as well so counter Cubit do increment comes over here and this looks good so it should work right now and if I click on it it still doesn't work so the problem isn't in counter Cubit instances being more than one now the problem is in this particular line now and the problem is that counter Cubit do state gives us the state of the app and it's a one-time thing it gives us the current state of the counter Cubit that hey right now I went inside and saw that the state of this entire class is zero so I can just give that value to counter and now counter is zero so it will display zero but when the button is called the State updates inside of it but it doesn't notify the counter class that hey the value has changed over here it doesn't say that to this particular line to prove what I'm saying convert this Arrow function to a block body and I can just call set state if I do this I'll restart my app and click over here you see it starts working it starts working because I've incremented the counter Cubit over here so the value of the state is now one and then I call set state which triggers the rebuild of this build function so this counter is called again and because of that counter Cubit do state again goes to the counter Cubit class and asks hey what is the state over here okay so the state is one I can just display one right now but we don't want to use set State inside of this how can we do it without set State I said that emit function updates the state and notifies all the listen n about the updated State we're not listening to the state yet we're just getting a onetime value from it using this line if you want to listen to the state what we can use is a widget provided by block and that is the block Builder widget so what I can do is wrap this entire scaffold if I want I can press control shift R to get this dialogue box and I can just wrap it with the builder which would be block Builder and obviously don't forget to import the flutter block library at the top after that I would get access to the Builder function and the Builder function gives us context and some value the value it is giving here is the counter value but along with that we also need to pass in a block so I can just take in a block over here and I can pass my counter Cubit instance right over here and it would accept that why would it accept Block in counter Cubit space because if we just go to the implementation of this block Builder we'll see that the block which is B value should extend State streamable and if we go to Cubit it extends blog base and blog base extends State streamable source which ex which implements state streamable so we can use counter Cubit instead of block over here and what this block Builder does is basically based on this counter Cubit it will give us the value of the counter and even over here we can mention that the type is counter Cubit and integer if we don't mention it the value of the counter will remain an object it doesn't know yet what the value of the counter is so we need to specify it over here that the block is counter Cubit and the state value is integer so now this is an integer and there we go now if I restart my app and increment this you see it starts working and that works without using set state in the entire code so just to recap blog Builder is basically a widget that flutter block provides to us and it requires two arguments block which is not a required argument and we'll talk more about why this isn't a required argument why it's an optional value and the required argument actually is Builder and whenever the state of this block changes the Builder will be run again so this entire Builder will be called again as soon as the state inside of this counter Cubit changes so I think you can understand a little bit of problem in terms of optimization over here if the state inside of this counter cubit changes this entire scaffold is rebuilt but this entire scaffold doesn't have to rebuild whenever the state of the counter Cubit changes only this text has to be rebuilt so we can modify this code a little bit to optimize the app further instead of rebuilding this entire screen we can just rebuild this particular text vdet whenever the state changes so I can just remove this entire block Builder from here now we're back to the normal app and I'm just going to wrap it around the text so we just have a block Builder over here and I can just tweak it a little bit to return a text over here and that's all so now our Improvement only modifies or rebuilds this text widget whenever the state changes instead of this entire scaffold so that's a good Improvement and blog Builder May makes that possible so if I restart just to prove it to you everything works as before so just to get a little bit of practice I can just wrap this Floating Action button with a column and I can just create another Floating Action button which is of decrement and we can just see how we could Implement decrement in counter Cubit so I can just use icons do minimize let's say yeah and I can just save it so we have our two buttons over here just to get the layout right I can just use main access alignment as main access alignment. end and both the buttons are over here now whenever I click over here I want to decrement instead of increment I challenge you to try this on your own and see if you're able to do it so pause the video and try it on your own I'll just go to counter Cubit and start working on it so I can just use void decrement and I can just do emit State minus one that's what my ultimate state is going to be right whatever value I have I just want it to be minus1 and after that I can call the decrement function over here and now whenever I decrease it would decrease and whenever I click on increase it increases that's great but let's go a little bit advanced in this what if I want it to stop before zero so if I hit minus right now it shouldn't go to negative 1 it should just stay at zero and when I increment it can go up till Infinity so my bounds are from 0er to Infinity how do I implement this logic pretty simple right I can just go to my decrement function I can just check over here if state is equal to zero then I don't want to do anything so I can just return over here so if state becomes zero I want to return so that I don't call this function and because of this I would never go below zero now if I run this I'll call decrement it doesn't decrement but if I click on increment and decrement it works up till zero and that's the logic the point of doing this was just to show you how clean a code can be using cubid all your state logic comes in one particular class and all of your logic stays inside of this function nothing is thrown into the UI all your logic stays in counter Cubit and that's the big advantages these State Management Solutions offer another important thing that I wanted to tell you is I cannot call counter Cubit do emit outside of this counter Cubit class even though it allows me to it does add a warning saying the member emit can only be used within instance members of subclasses of whatever ever is written over here EMT is a protected function since it's a protected function I cannot use it outside of my Cubit I cannot use it outside of this counter Cubit class I should be using in this class itself so that's one thing to keep in mind another question I have for you is what if we had two pages on the first page we only saw this and we didn't have any increment decrement functions and on another page we had the increment and decrement functions or increment and decrement buttons how would we do it then let's go ahead and try it out so I can just call this page for a lack of better naming skills I can just do increment decrement page. do I can import material do do and I can create let's say a stateless widget which would be increment decrement page right and now I can just create a scao and we're not going to focus on the UI skills right now so I'm just going to take this Floating Action button from the homepage and put it over here so I can just take this Floating Action button and put it over here there we go so now I need access to this counter Cubit instance now I can get it through the Constructor but I'm planning to use G router for routing to route from this page to the other page where my increment decrement page lies I'm planning to use gouter there I cannot pass like the counter Cubit instance from there so how will I be able to increment the function if I just create another instance of counter Cubit class it would just be the same thing we did in the beginning and it would not work we would be creating two separate instances of counter Cubit class so how can I pass this counter Cubit and that's where you would think that provider would come in handy right we could just use provider to provide the instance of this counter Cubit class once so that we could access it from anywhere in our app so if we had provider with us we could just go to the main. dot file I would wrap my material app with the provider widget I would provide the instance of this counter Cubit class and then I could access that counter Cubit instance from anywhere inside my app but unfortunately we don't have provider with us or do we well we do block behind the scenes uses provider to provide instances of block and it gives us access to one nice widget with that if I just press control shift R again and wrap it with a widget I have access to One widget which is known as block provider and if you see this comes from the flutter block package only we have not installed provider package block package gives us access to block provider which we can use to provide instance of block from one page to another so so how would how this would work is we would just create block provider over here we have to pass in a create argument which would accept block Cubit anything you want I can just pass in my counter Cubit instance over here and we also need to pass this as a function so we can just do this and that's it now we can access the counter Cubit instance from anywhere in our app just like we would using provider so this is kind of like Prov but when we use block provider we can only pass blocks we cannot pass normal classes they need to be of the type State streamable Source now I can just go to my homepage and over here instead of creating a new counter Cubit instance I can delete it and instead use the counter Cubit that we get from the Block provider I can just use final counter Cubit is equal to block provider is the same syntax as provider we would use provider. off context to get access to it but here we would just do block provider. off context and here we need to pass the type of the block so the block I'm using is counter Cubit and then we have our counter Cubit with us and now because of this we don't even need a state full widget we can just be satisfied with uh stateless widget and instead of using widget. title we would be using title and that's all so this should work and now I can do the same thing over here in my increment decrement page I can just take this go to the increment decrement page paste it over here of course make sure you import all of the things and now you can just take this counter Cubit to increment decrement and yeah that's how we'll be able to work now just to test it out I'm just going to go to the homepage and here let's create a floating action button again but this time the onpressed is going to be well navigation and the child is going to be an icon that basically says that we want to navigate I can just use navigate next and now I'm not going to install go router over here but you can think of it that way that if you're using go router you could not pass instance of the block of the counter Cubit and because of that it would cause problems also it would just be so annoying just to pass counter Cubit every time you navigate to this page let's say your app has 100 Pages it would be pretty annoying to pass a counter Cubit instance every single time so this solution that we used using block provider is a neater and a better solution overall but right now I'm just going to use Navigator because we're not adding any other comp package complexity and I can just use push material page route context and I can just go to the increment decrement page and now when I click over here I go to the new page I'll increment this and you see it is one now I'll again go to to this page I'll increment it and it's five now since it's the same counter Cubit instance that's being updated over here and the same counter instance that is being displayed over here we get the same results and that is the beauty of State Management overall and thanks to block we don't have to install provider anymore we can just use block provider to provide a blocks of course if you have other classes to provide you can just use provider as well but block provider provides the guarantee that it's always going to return a block or something related to block obviously this is a cubit but something related to a block so that's our end for the counter Cubit now we're going to dive into block and see how we would manage State using block instead of Cubit I'm going to keep the same Cubit code and I can also keep the same layout homepage and increment decrement page so that we know that the state is being managed globally it is being managed app-wide instead of just on one single screen so let's get into State Management with block now so similar to a cubit we'll be creating a folder for Block as well so we can just write in block and you'll see there are different icons for block and Cubit it correctly identifies them and in here I'm going to create counter block dot dot and it serves the same nam in convention counter is the state that I'll be managing so that I get an idea of what I'm managing and block tells me that I'm using block inside of this file and then I can click enter then I'll create a class called as counter block but instead of extending it with qbit I'll be extending it with the block class that comes from the flutter block package as well and we get the same error that the super class doesn't have a zero argument Constructor so we need to create a Constructor which says super as zero because at the end of the day we're just managing the count over here so it's going to be an integer again so that was pretty similar to Cubit right where's the difference if you remember in Cubit we passed an integer over here saying that our state has a value of an integer but in Block just passing integer isn't enough block requires two arguments over here you see it requires an event and a state in cubit only the state was required because there was no concept of event and Cubit block has the concept of event so what are these events events are the input to a block so if you have like a button press that is an event that can be captured and sent to this counter block using which we can update the state so in Cubit we had to create a function and we could call that function but in Block there's no need for that we can just create our event and based on those events we have to create event handlers and then the state will be updated so let's see it an action so how should I create my event to create an event you can just create a class so let's say I want to have an event which says counter incremented let's call it incremented and that would be my event right how that's how easy it gets this is one event the naming convention for an event is like this because first we need to mention the name of the block which is counter followed by the action that the event is performing and the action it is performing is it's incrementing so it's counter incremented and the reason we have to put this counter before is because let's say we have hundreds of blocks created in our project later on we'll get confused if we just name it incremented if I just say incremented event was called it can be quite confusing where is this incremented event even there it's in the counter block right so I can just call it counter incremented now I can just take this event and pass it in over here right and that fulfills my block that's all it ever wanted an event and the state now I can just provide this block just to see the initial value I can go to the main do do file and I don't want to remove remove this counter Cubit just yet I'll remove it later on so I can just have another block provider created over here so I can just do block provider create and I can return my counter block from here and obviously the child for this is going to be the material app so let's take this material app and paste it over here easy but you see the nesting can be pretty deep and provider has already taught us that if the nesting goes way too deep we can just use multi- provider in Block there's a similar thing called multiblock provider we can just use that so here we can just pass in a list of providers and I can just pass in Block providers so I'll just pass in my counter block I also need to pass in my counter Q bit so let's copy this and now I think I can remove my block providers from here and there we go so instead of nesting block providers inside of each other I've just created a multi-block provider which requires a list of providers and there I have it no more nesting and it should work the same way so let's see if it still works I'll just increment I'll go back and it's on four so it's still working now that I have counter block provided I can just go to my homepage and instead of using counter Cubit over here I can just use counter block right so here I can just pass in counter block and I don't even have to pass counter Cubit anymore so I can just do final counter block is equal to block provider do off counter block context so this way we get access to the instance of the counter block which we can just pass it over here and there we go if I restart it would show the zero for me but when I try to increment it it won't show the updated value because we're using counter block and the changes are happening in counter Cubit another interesting thing that I can show you is we don't have to pass block over here anymore we can just do this and it would still work the reason for that is we've already specified counter block over here since we've already specified counter block and we've not specified any block value over here because of which it is optional what block Builder does behind the scenes is it goes up the viget tree trying to find a block provider that returns counter block and once it finds it it will take that instance and that will be the block it will build on and the same goes for Cubit I don't have to write I don't have to mention counter Cubit over here I can just do this and just to prove it to you I'll restart I'll come over here increment it I'll go back and you see it is six so only if you have created providers at the top you don't have to mention the block if you've not mentioned the providers at the top and you're just creating an instance then it needs to be passed in because it doesn't know counter Cube bit instance was created anywhere so keep that in mind now we'll again change back to counter block and as a result we don't even need this so we can remove it so now that we can see the initial State let's go ahead to our counter block and see how can we respond to certain events so we have a counter incremented event as I said whenever we have a certain event that was created we need to create event handlers for it and they can't be any functions so how do we create those event handlers to create those event handlers you can just create a body of the Constructor and in the body of the Constructor we can type O N and once we type O N the first thing we have to do is create a generic type over here and ask what is the event that we want to capture over here I want to capture the counter incremented event so I can just do that so on counter incremented I have an event that I get and the emit function event is the event that was captured so counter incremented because that's the event that we're capturing and emit is basically updating the state in Block we cannot use emit outside of these handlers so if I just create let's say a function and here if I just say emit it does give me access to emit but it gives me a warning saying the member emit can only be used within this package or a test file we cannot use it over here so that is the difference between qbit and block the emit function will be given out by an event handler to us so we don't have to worry about that and now whenever the counter is incremented we just have to do emit State + one and we do get access to State over here State comes from the Block class so that's all good and that's all we have to do we have to create a block we have to create an event and based on the event we have to create a event handler and based on the event handler we have to update the state now I can go to the increment decrement page and instead of using block provider of counter Cubit I can use block provider of counter block and you see it doesn't have increment and decrement functions anymore so let's update this it's counter block and we can do counter block Dot and it will tell us the list of functions that are available on this instance of the class so many of the functions are same like close emit on on change on error but we have to use add when we use add you'll see that it requires counter incremented event so it needs an event which is well counter incremented so I can just add the counter incremented over here and we're good to go temporarily I can just uncomment this because we have not implemented decrement event so let's restart the app and see if it works I'll come over here I'll click on this navigate button I'll click on increment I'll just do it a few more times I'll go back and it's five the state management using block is completed what we have done is on this instance of counter block we've added an event and the event is counter incremented as I said we cannot call functions on block so we need to use events and add them to the block as soon as we pass it to the block the block will run this and see hey which event was captured counter incremented was captured okay let's run the body of this counter incremented event handler and then it would update the state and then we have our usual conf configuration in the homepage of block Builder that rebuilds this thing whenever the state changes so that's a neat solution now let's do the same for counter decremented I can just do class counter decremented and now I can do on counter decremented event Emit and there we go but why is this giving me an error it is giving me an error because it says counter decremented doesn't confirm to the bound counter incremented of the same type parameter e try using a type that is or is a subass of counter incremented the basic problem over here is you've said the event is going to be counter incremented and it can only be a counter incremented event then so what about other events I have other events in my app there's not just one event I also need to pass in a decrement and I cannot pass in a list over here neither can I pass multiple events so how should I go about solving this problem it does give us a hint over here it says try using a type that is or is a subass of counter incremented it is basically saying that hey you need to create a parent class which has multiple events attached to it so what we need to do is create like a super class over here and this super class will have multiple events attached to it so there can be counter incremented then there can be let's say another event which would be counter decremented and there could be a third let's say counter restarted so these are the three events that I can create from this particular parent class so I can just go ahead and create a super class now this super class can be any class you want but I'm going to take advantage of the dot three modifiers that were released previously in the year so I can just do sealed class counter event and extend all of these classes with counter event but why did I choose this to be a sealed class the reason I've used a sealed class over here is because let's say I have a switch with me let me put it out void function and from this function I'm getting a type of counter event I don't exactly know what the event is but I just know it's one of the counter events and I can create a switch based on this event there's no notable difference over here but if I just extend these classes with counter event I can just have counter event over here you see we start getting errors saying the type counter event is not exhaustively matched by the switch cases since it doesn't match counter incremented it basically starts telling me that hey you've not put one case over here you've not put the case of counter incremented it gets to know which classes extend counter event so if I just put case counter incremented we're good but after that let's say I also extend it with counter event it gives me me another error saying that we have not passed a counter decremented so that is the benefit sealed classes give us over abstract class you could use abstract class but that's the benefit I see with sealed class that's why I'm going forward with it if you want to know more about these modifiers you can check out My3 video all right so now the change I have to make is instead of using counter incremented over here I have to put an counter event and now the error goes away because counter increment extends from counter event and counter decremented also extends from counter event and one small Improvement I can do is just put a final before both of these classes and the reason they were made final is that these classes if they're final cannot be extended implemented outside of this Library so that's a good thing for me all right so if we have a counter decremented event I just want to do emit state minus one and that's all now you see we have our counter block and a counter events in the same file and it can be pretty confusing if you have more than just two events over here there can be 20 or 30 events so it would be a good idea just to shift all of these into a separate class of their own so I can just go to block and create a new file over here called counter event do dot then I can paste all of these three classes then I come over here to count a block and import them in but instead of importing there's another thing we can do we can just use part over here so that they're considered as a single unit so I can just do part counter event dot dot and in counter event I can do part of counter block dot dot with this the error goes away what this is basically saying is that counter event is a part of counter blog. Dot and here we are just specifying that we have a part of counter event so with this we don't even have to import it and we can do multiple things with these counter incremented for example I said these counter incremented classes cannot be extended outside of their Library so if we imported it we wouldn't be able to extend the counter incremented class but now we can because they're in the same library and they're considered as a single unit another thing you might notice if if I just remove these things in increment decrement page we get an error the error is there because we've not imported counter incremented over here we have to implement that from the counter EV event class but if I just use part and part off the error goes away because they're all inside of counter block do dot they're considered as a single unit so I hope that was clear that was a lot of explanation I agree I can just restart the app I can go to the new page I'll increment a little decrement a little until we get to zero and the reason for that is in the increment decrement page we forgot to add the event of counter block over here so let's add it counter block do add and we can add the event of counter decremented we can save this restart it and now I can press this one 2 3 four times and this two times now I can go back and the output is two if I want to decrement it further it can be -2 but we can also add the logic in counter block saying that if state is equal to zero then we want to return from here simple the same logic that we added in counter Cubit as well so that is the difference in the code between counter block and counter Cubit you can compare it on your own and see what differences there are we're going to dive into more differences as we move forward in the tutorial but the differences that we've already covered are that block relies on events and cubits rely on function the functions need to be called and these events needed need to be added to the counter block the emit function is also not available outside of these event handlers in Cubit the emit function is available for all the functions one interesting fact about block and Cubit is that if we just go to their source code we'll see block extends Block Base and if we go to the Cubit source code Cubit also extends blog base that basically means that both of them have the same public API and that's a good thing so that's all there was to cover with respect to the counter app now let's dive deeper into the cuit by creating a to-do list so the next app that we're going to focus on is the to-do list app you can find the link to the beginner files mentioned in the description below so let's explore what we already have in the lip folder we have three files main do dot which contains the material app with named routes passed to it and the Home Route is the to-do list page which only has an AB bar a body that we need to implement and The Floating Action button which takes us to the new page so this is how the screen looks like and when we click on this Floating Action button we can add a new to-do which takes us to the add Todo page and it only has an abar a text field and an elevated button so we can add it to do from here and once we add it we want to display it on this screen over here just a very simple to-do app for this we going to use the Cubit State Management we're not going to implement this with block however if you want after the Cubit one is done I would recommend you to try this on your own and see if you're able to do it with block so as usual in the lip folder we first going to create a cubit and actually instead of creating a Cubit folder and everything by ourselves I have a shortcut that I wish to show to you if you go to the extensions tab in vs code and search for Block you'll see this package by Felix Angelov who is also the creator of the block package you can just install this vs code extension which will provide us with the tools to create blocks and save much of our time and now if I just press command shift B and type in new qit you see we get this option to create a new Cubit we can just click over here and then we need to pass in the Cubit name the Cubit name is going to be too and we don't have to add to- doore Cubit it will do that automatically we just have to pass in the Cubit name and click on enter and then we need to specify the location where we want to create this so I just need to do this in the lip folder so I'll just select the lip folder and there we go we have a cubit created with too Cubit and do state paths to it now if you dive into the files you'll see we have a to-do Cubit which Imports the block package and the meta package and it also creates to-do state which basically creates the state now we don't need state for our app so we can just remove this file and then go to to-do Cubit and remove these two packages as well and even this line now we need to import the flutter block package so first we need to install the flutter block package so we can just do command shift p again and type in add dependency and then type in the package name which is flutter block so with this it would add the flutter block package to our pope.l file there we go and now I can just import the flutter block package right over here at the top nice now a little boilerplate code is already created we want to pass in the to-do State and the initial value of the state so let's put both of them now what is our state going to be essentially this Cubit is just going to store a list of to-dos in our app whatever to-dos we create we need to store them in the State Management tool which will be used to display it on the screen so that's our Purpose with to do cubit so it should be a list of to-dos right now I don't really have a to-do created so we could just do list of map of string but I always prefer to create models for my toos so I'll just go in the lip folder and create a model for to-dos it just structures my data really well and I prefer it that way so I can just create a to-do model do Dot and call it let's say just too now it's going to have two Fields final string name and final date Time created at so what is the name of our to-do and when was it created now I can just create a Constructor for it and to create Constructors and data classes really quickly there's a nice extension you can use which is the do data class generator extension over here here you can install this and it will help you create Constructors data classes really quickly so I'll just create I'll click on generate Constructor I can remove this line and there we go now in a DAT uh to-do Cubit my state is a list of to-do right now I also need to import the to-do model there we go so my state is list of to-dos and my initial value for the list is going to be empty right so I can just pass in an empty list like this and there we go now that we have all the initial setup done and I hope you've understood what we have done over here so just to recap we have extended it with Cubit then we have a list of to-dos that are going to be our state because every single time we add a new to-do we have to store it in a list which will be displayed on the main screen and the initial value for the state is going to be an empty list now we need to provide this Cubit so I can just go to the main or do wrap my material app widget with block provider widget and if you scroll down you'll see we have block provider over here we get this option because we' have installed the Block vs code extension so now I can just wrap it with block provider and the name is to do Cubit so I can just use that there we go and I also need to import block provider so I'll import that on the top nice so now that we have done this we can just go to the to-do list to display the list so here to display a list we have to use a list view Builder we already know that we get a context index and then we have to display it but what is our item count going to be to get the item count we need to get the length of the state from the cubid and for that we've already seen we'll be using block Builder so we need to wrap this list view Builder with a block Builder so I can just wrap it with the block Builder widget and then we need to specify the type of the block and the state so it's going to be to-do Cubit and the state is going to be a list of to-do that we're going to get all right also make sure you import the flutter block package over here as well and there we go so we have the body as a list view Builder but then we realize that we need to get the length of the state so we wrapped it with the blog Builder to get the state value we've already seen this before in the counter app as well so I'm rushing through it now in the item count I can just do state DOT length right the state that I get here I'll just use its length but just to be more descriptive I can just name it as to-dos and then call it to-dos do link because the state is essentially giving me a list of to-dos and now in the item Builder we can get one particular to-do which will be to-dos at one particular index and then we can return a list stle where the title is a text of too. name and this is why I created a to-do model if you were confused used when I used map string comma Dynamic I wouldn't get this auto complete thing over here now it auto suggests me to use name or Creator at if I used a map I wouldn't get that I would have to do something like this and it could possibly be misspelled or anything that's why I created a model so that we have more structure to our app and a code and again just to remind to you this block Builder doesn't have a block over here it automatically go goes up the widget tree trying to find to-do Cubit provider and once it gets that it uses that value once we have a provider created we don't have to worry if we specify block over here or not but if you don't or you want to let's say override the value then you can use the block over here and it would work just fine for you so now on our screen we are not able to see anything because initially the list is empty now we want to update that empty list to fill in some right so as soon as the user clicks on this add button in the to-do we want to add it to the list so we can go to to-do Cubit and here we can add a function called add too it's going to get a string title and then based on this title I can create a to-do right so I can just do final to-do is equal to too the name is going to be the title and created at is going to be datetime do now because it was created literally just right now and then I can emit that to-do is that fine not really because if we emit a to-do we're just emitting one to-do we want a list of to-dos to be emitted and if I just wrap it with the list it would throw away all the errors but every single time we create a new to-do the previous one will be overridden so if I create a to-do let's call it hi and click on ADD it would be added over here but when I again try to add another to-do let's say hello the hi to-do would be replaced by this hello to-do because our new state is just one to-do our new state should be the previously existing to-dos along with the new to-do that we created so to do that can we just do this state. add too and then I can just emit the state that should work fine right let's see if it works what I'm going to do is go to the add to-do page and as soon as the user clicks on the add button I just have to call this function the to do function so I can just use block provider do off context and then I need to provide the name of the provider so it's to do cubit dot add too and the title is the to-do title controller. text. trim too title controller is the controller that was attached to this text field and in case you're just irritated by how long this blog provider of context is there's a shorter way you can use this and that is context. read to do Cubit and then call do add to do on it so this is a very similar thing to provider it's present in both the things you can use blog provider. off context or you can just use context. read it would work fine both the places all right so now I'm just going to restart my app and click on ADD to-do I'll add High click on ADD then I'll go back highest showing up that's nice now I'll add another to-do let's call it hello I'll add it I'll go back but I don't see Hello over here maybe it was a glitch I can just try again right I can just type hello again and then if I click on ADD go back nothing happens the state is as it is let's try to see where the problem was I'm just going to go ahead and print the state and see what it always gives me I'm going to restart my app as well now I'll click on ADD too hello I'll click on ADD I'll go back hello shows up and it says instance of to-do over that's good now I can again type in hi there I can click on ADD go back it still doesn't show up but the state is updated and it is instance of to-do instance of to-do it shows instance of to-do two times that means a list is being updated and everything seems to be working fine over here so why are we not getting the real output on the screen and to understand the reason we must hover over this emit function and read this section it says emit doeses nothing if the state being emitted is equal to the current state so emit doesn't notify any of the listeners if the state being emitted is equal to the current state if this state is equal to the current state of the Cubit and current state of the Cubit is known when emit just asks this to do Cubit that hey what is the state over here and once we call state. add we're basically saying our current state is this too so the current state and the state that you're emitting is the same thing which is why it doesn't notify its listeners just to demonstrate to you in terms of a diagram let's say this is our current state and let's say our current state is having one to-do already the name of this to-do is let's say one just so that we have less complexity now we get a request to add a new to-do once we get a request to add a new to-do what we do is take the title then we create a to-do out of it add it to the state this is the current state so I just take the to-do and add it over here so now my current state is having two to-dos and then I'm emitting this current state if I'm emitting this current state the current state and the state that I'm emitting are the same thing so it thinks nothing has changed and because of it it doesn't know notify the listeners that the state has changed and the same thing happens when a third to-do is being added a third to-do is added to the current state so this part is done and then we are emitting the state we're emitting the same current state so it's thinking current state is equal to the state that is being emitted so it's the same thing we don't have to notify the listeners about it this is why we don't get any updates so how do I make sure this works what I can do is instead of using state. add so what I can do is once I've added the state I can just create a new list based on this so I'll just do this and then I'll put three dots which is a spread operator so doing this we get each of the elements in a new list that we created so this is different from the current state that we have so the state that we are emitting it looks very similar to the current state but it's not equal they're not equal to each other they have a different identity this is a separate list of its own and this is a separate list of its own and that's what we've done the elements are the same but the identity of the object is different and that's why this should work let's go ahead and try it we're going to restart the app I'll click on ADD too I can just say hey click on ADD I'll go back he is showing up let's try to do the same thing High click on ADD go back and the high also shows up now I can add a third value go back and it shows up so now this works alternatively what we could have done over here is instead of just doing this we could have created a new list over here and then add it to do this would have the same result what we doing is saying that we want to emit a new list which encompasses everything of the previous list plus a new to-do and now we'll be able to see the new output so I can just click on high that shows up I'll do it again hello and it shows up nice so now that we able to do it I just want to make one small change and that is whenever a new to-do is added I can just do Navigator do off context do pop so it would just pop the screen so that we go back to our default or the home screen so I'll just say hello there we go and it's able to add new to as well so our state management using Cubit is done but there's more to cubeit than just having functions that would change the state and super there's more you can do which will help in developer experience you see every time we have to debug if the value changed or not we have to put a print statement over here and that's not a cool thing what if I don't want to put print statements every single time I want to get a log of every single time a value in a cubit changes to do that I can just use something known as on change which is provided by the Cubit using on change I can just print the change and see what it has for me so I can just do this now I'll restart my app I'll press command J and come to the home screen let's add new to-do so I'll just say hello click on ADD and now if I come over here you see it says there's a change and the change is that current state has been changed from an empty list to an instance of to-do that's really helpful for me because I get to know that hey the change has occurred the current state has changed and it would be really helpful for me if I have like 100 cubits and I get to know that certain Cubit has changed now to make this more specific you can just add the Cubit name over here as well so it's the to-do Cubit that has caused the change so I can just do this and now if I just add a too again I'll click on ADD and here we have too Cubit has a change that current state has changed from an empty list to an instance of to-do now just in case this instance of to-do is bothering you and you really want to see the elements inside of the to-do you can just go to to-do model and here click on this bulb icon and click on generate two string this would create a two- string method for you because of which now every single time you create a new to-do let's call it high it would say that the change is current state which is an empty list to next state which is this to-do it shows the elements of the to-do so that it's helpful for us it no longer shows just instance of to-do so that's one cool thing you can do with Cubit another cool thing is the on error method that you can use provided by Cubit again every single time you have an error you can just print the error over here and see what what the error was now to see this in action what we can do is just put a check over that if title dot is empty then we want to throw an error that hey you cannot just put a title that is empty so I can just put add error and then I can say title cannot be empty all right and I can just return so that no further execution in the function happens now I can restart the app and now if I try to add something it doesn't add it to the list that's good and it prints the error for us which is title cannot be empty now again just to make this more specific you can use string interpolation over here and do to-do Cubit as error now again if you try it you'll just see to do Cubit title cannot be empty and it doesn't add it to the list so that's another cool thing you can do so that's pretty much everything you might want to use in Cubit so with these simple little things you can modify your code to be much better in terms of programmer experience so that's everything I wanted to cover with respect to Cubit the main advantage of Cubit is that it's really easy to use especially when compared to block you can just create your own functions and call those functions in Block you need to create events you need to create event handlers all of that stuff so that's one advantage Cubit has over block and one of the reasons you might want to use Cubit over block but now let's dive into block so the next stab that we're going to work on is the login form validation app to get these beginner files I've linked it in the description below you can check it out and install it in your system so just to walk through this this is what we have the there's only one screen in this app which is the login screen and this is how it looks there's a text at the top there are two buttons which are the social buttons and there's a separate widget created for it over here then there are two login fields which is like the email and the password field and after that we have a gradient button which is again in the widgets folder so that's all there is to this app now what we want to do in this is use block to add validation to this app so basically whenever I enter email password and click on sign in it should give me the approve appropriate errors if there are any errors for example if the user did not enter a valid email or did not enter a valid password then just show a snag bar or something and if the user is successful then we'll go to a new screen which shows the user's email their password and all of that stuff so first thing I'm just going to install the flutter block package after we've installed the flutter block package the next thing we want to do is create a separate block file for this authentication so I'm just going to click on lib right click and you see we have an option to create a new block alternatively again we can just do command shift p and just say new block and we would get that option but this is just another way of doing the same thing so now it asks us for the block name my block name is going to be o and I can just click on enter and you see it creates a new block package over here it has o block O event and O state in it we already know what O block and O events are we ourselves separated them in two different files in the counter application let's go into each of the file and see what it has to offer for us so there's o block now it has two files here block and meta we don't need any of them we only need the flutter block package which we can import there we go then we have our AU block extending block the event is O event and the state is O state in our counter app the state was an integer but in this case it is going to be or state and we're going to understand why then we have a Constructor with o initial as the super argument and then we have our event handlers created so our first event handler is on Earth event itself so any event that's added over here will be handled in this particular event handler now let's go into o event in O event we just have a sealed clutch which is the O event and it's immutable so if you want to keep it immutable you can just press command full stop and import foundation. do but I'm fine with not keeping it immutable also so there we go now in case you don't want to import any flutter related files over here you have to install meta which was present over here by default but I don't mind that I can just have Foundation do dot over here so the foundation do do here is present only because this immutable is present in one of the files that is part of O blog. do and we've already understood what part and part of means in the counter application so I'm not going to dive into it then we have a third file which is the OD state it also has a sealed class which is immutable and a final class which is of initial now let's get our objective straight with this Au block what is it supposed to do what I want to do is as soon as the user clicks on sign in I want to handle that event right so I'll need events like login button pressed or the user is trying to login that event and what should the response to this be the response to this would be well just that if it's a success or a failure so was this sign in button clicked on was this a successful event or there was an error the error could be that the email was not entered password was not entered password was six characters or less and email was not a valid email so those are failure things and the success is just that the sign in is successful we can just go to the home screen and see the user with the new email so now that we have clear goals about what we want to do we can just go to Au event and you create a new class which is login requested right so we can just do final class or login requested now instead of naming this Au login requested we could also name it Au login button pressed and that would be fine as well I'm just going to call it Au login requested and this should extend the Au event so we have a event created now the next thing I want to do is well create a event handler right but before that I want to manage the state as well so what is the state going to be as discussed before it's not going to be integer like before or a string like before we have a special state that we want to emit we want to emit if it's a success or it's a failure and that is not provided by flutter by default so we need to create our own class saying that this is au success State and this is the Au failure state so we can go to Au state. dot now obviously you could create your all states over here as well and that would be fine but as mentioned before in the counter app that we don't want to pile up everything in just one file this file is just related to or block and or event will be related to everything about events and OD state would be everything related to state so here you see it has a sealed class of O State there's o initial now I want to keep this class because that's what my initial state is going to be I'm not going to say that my Au State initially is going to be a success or it's going to be a failure because I don't know if it's a success or a failure it's none of those in the beginning of the app when the app starts it's none of them it's just Au initial that's the state it's just in the initial mode after some input occurs or something occurs the O State can be o success or o failure so I'm just going to keep this class as it is and thank block for creating it now I can just do final class or success which would extend or state and I can create another class which is O failure and extend that to Au State awesome so we have our three states with us initial success and failure now let's catch the O login event so I can just do on o login requested I cat that and now I will implement this event handler so as soon as I get the Au login request what do I want to do and in a real life scenario what I want to do is get the email get the password and check their validity so if the email is valid or not or if the password is less than six characters long or not but right now I don't have access to either of them how do I get access to it well for that I would have to capture those events and those inputs from the user so let's go to the login screen and try to pass it in so in the gradient button we have to create an ontap function so onpressed over here is empty what I want to do is just take this onpressed from The Constructor so I have void call back and I'm going to call this on press and I'll require this on press from The Constructor I'll also take this on press and pass it over here now I can just go to the login screen and in gradient button it is going to be onpressed like this so as soon as the user clicks on this button I want to take the email I want to take the password and pass it to the user to do that first I would have to get access to the block and Au block is created but I've not mentioned it in main. file with the block provider so let's do do that really quickly so I'll just wrap it with a block Builder we already used to all of this now I hope so we can create O Block I'll import flutter block package I'll import the O block. do file and there we go I know I've rushed this a little bit but we're just creating a block provider and returning the Au block from here now I can just go to the login screen and in the onpress whenever the user clicks on the sign in button I'll call the Au login requested event so that my Au block can handle it so I can just do context. read and we've already seen this with Cubit this is also accessible in Block we can just do Au block and then call Dot add and we'll add the event of au login requested but now you see the problem the problem is I cannot pass the email and the password from here add doesn't have any other Constructor to take it just has an o event that it can take it cannot take any arguments that are provided so how do I pass it in well the solution is just to go to 's login requested event in AU event. do and here we will accept email and the password so I can just do final string email final string password and then take that from The Constructor so I'll just create a Constructor for this field and there we go now I'll also put comma so that the formatting is correct now what I'm seeing is that every time we use this Au login requested event I have to pass the email and the password from The Constructor and because of this in the login screen now since I've called off login requested class I can pass in the email which is email controller. text. trim and password as password controller. text. trim that's pretty much everything we have to do in the UI part now I can go to the Au block and access that so I've already mentioned that this is an au login requested Handler so I can get access to the email and the password from this event this is also of the typo login requested right so I can just get the email saying final email is equal to event. email since this is of the type of login requested I can get access to the email and the password property and similarly I can also get the password which will be event. password simple now I can perform any validation or sanitization I want I can just check if password. length is less than six if it is less than six then I want to emit a state saying that there's a failure so I can just say emit or failure but along with the O failure I also need to pass in some message telling that what exactly is the O failure what went wrong we need to tell the user right otherwise we'll just tell them that there's an error but they don't know about the error we want to give them input about the error so in the Au State as well we can go to Au failure and here ask for the error message or just error and we can create a Constructor for that as well I don't want it to be a named argument I can just pass it as a positional one so that I can directly mention over here password cannot be less than six characters simple right and we can perform a similar validation for email as well now you can use reject for it and that would be a good choice but I'm not diving into all of that I'm just putting in a comment saying email validation using reject all right so you can do this on your own I've already done the validation for password length and we also need to return this because we don't want further execution to happen it will emit this and after that it would continue forward emit is not like a return so we need to specify a return over here or if you don't want to do it in two lines you can just do it in one line doing a return like this because emit does not return anything now that we have this out of the way you know all of the validation and sanitization can be performed here now let's say everything was successful all right now how do I emit this so I can just do await future. delayed and you see we need an await call over here so I would want to put async for this function which I can put on function can be asynchronous as well and that's a good thing so I can just put a weit here and say future. delay duration seconds 1 and it would be a constant now what why am I doing future. delay just think of this as a mock service call that I'm doing so just imagine that you're trying to talk to your database to fetch the details of your user once the login is successful and all the validation is correct so you're trying to get their data this is what I'm trying to mock over here that the data is coming from an external API that you've created or to put it more simply the data is coming from your database so that's what I'm just mocking over here so after a delay of 1 second what I want to do is run a fun function here saying there's a success so we can just do return emit or success right but again with success I want to pass in some user data so I can just go to the all success class and here I can just create final string uid and accept that through the Constructor so I can just create a Constructor and there we go now instead of having just a uid it could be let's say a user model as well so if you have a complex application you might have a user model where you want to store the user data for us it's a uid so let's pass in the uid and my uid is going to be based on the email and the password so I can just do dollar email dollar password and that's my uid in a real world application this uid is going to be the one that comes from your database and of course since there's an async aate over here and we just just assuming that we're talking to a database and a repository we have to put a try and a catch block just in case any exception occurs so I'll catch that exception and I'll just return that so I'll just return emit o failure e.2 string easy and simple enough now let's go to a login screen and we've already added the Au login requested event so let's run it and see what happens so we can add an email over here which is let's say rrr gmail.com and test 1 2 3 I'll click on sign in and nothing really happens why because we don't have anything to display on the screen we're not using blog Builder anywhere or anything like that but do we even want to use blog Builder there's no State we want to listen to and display something else there's no State change that we want to display all we need to do is whenever the user clicks we want to tell the user if it was a success or not if it was a failure then I want to display a snag bar and for that I cannot use a block Builder block Builder is there just so that whenever the state changes our UI is Rerun that's all blog Builder does so I cannot use blog Builder that's clear what else should I use well there's block listener that we can use so we can wrap our entire single child scroll view with a widget called as block listener and over here we need to mention the block so it will be O block and O State as it is that's really nice and it gives us a listener argument now what does block listener do well based on the Au block event that it has it will listen to the state and if there's anything we want to do about it let's say we want to navigate to another page we want want to display a snack bar that's where block listener will help us so whenever the state changes this listener will be called again which is quite similar to blog Builder but in blog Builder the UI was rerun and rebuilt but over here we can catch the particular State and based on the state we can display a snag bar for example if the password is less than six characters I want to display a snack bar so I can just say if state which we get from here is O failure right this state can be of the type O State and O failure extends that o state so if state is O failure event that means something has gone wrong so I want to display a snag bar and that's where I can just do scaffold messenger doof context Dosh show snack bar and then I can create my snack bar with a content of text but what is my St text going to be well the text is going to be state DOT and you see it automatically suggests error to me now you might say that hey state is of the type a state right and if you go to a state a state doesn't have any argument that has error in it only Au failure has the error argument in it how is it auto recommending state. error to us and it is able to recommend that to us because we put a check over here that if state is Au failure so dot knows that we are in this particular if condition where the state is au failure so it auto recommends error to us so we can just take advantage of that and that's pretty cool right now I can just restart the app and let's say I put an rrmail.com again but my password is test now I click on sign in and you see password cannot be less than six characters so what happens behind the scen scenes is that when gradient button is clicked this event is run or login requested and then this event is caught in the O Block once it is caught in AU block it runs this entire function and then it checks every single thing if password. length is less than six it returns an au failure to us as soon as there's a state change over here our block listener reruns and because of that scaffold messenger is also run so that's what's happening now let's say there was a success what do we want to do in terms of success if there's a success then I want to move to the next page so what I can do is close all the other files I'll just keep login screen and along with that in the lib folder I'll create another screen which is the homeor screen do. file here I can import package flutter material dot dot and and along with that I can create a stateless widget call it home screen with a scaffold and temporarily let's say we don't have any body we'll get to the body part in just a minute so we have our home screen and that's where we want to navigate now I can go to the login screen and here I can put another statement that if state is au success then what do I want to do then I want to do Navigator do push and remove until where I'll pass the new route which is material page route and then I'll pass in the Builder which is the context and then I'll go to the home screen that's pretty much all I want to do so if it's a success I just move to the home screen and the user gets to know that they've logged in successfully so yeah now let's rerun the app and see if it works so I'll just put rrmail.com I'll put more than four characters now six characters now and I'll click on sign in and you see we move to the new page but just for a second there I thought that this didn't work and I didn't know that it worked because there was a 1 second delay that I had put in real life applications the deay can be much longer right so I want to display a loading indicator while everything's loading how do I make sure that happens to make sure that happens I can go to All State and now over here I can add another another event which is called final class o loading which extends the O State when I do this I've created a new state of loading and based on this new state I'll be able to display a new thing which is the loading indicator not that this was not put in AU event because Au events are basically inputs to our block so Au login requested is an input that we can give Au loading is a state it is in the loading state if you're familiar with Asing data how many types of State there are in Asing data there's three types of State loading success or failure failure is the error over there so that's why o loading is put in state not in O event now I can just go to O block and put in the loading state so as soon as the tri block is starting I can just put emit over here saying all loading has begun I'm not putting return emit over here otherwise all of this code wouldn't even run I'm just putting emit Au loading which means that the state has changed now it will load and now it goes into all of these conditions and if there's a failure it would change the state from loading to failure if there's a success it would change the state from loading to success so that's a pretty neat solution now I can close this I can go to the login screen and here handle that loading event so if state is off loading then what do I want to do I want to display a loading indicator so to do that I need to return a circular progress indicator right now here's the problem circular progress indicator cannot be returned from here this block listener doesn't do the job of rendering the UI it only does tasks like showing a snack bar navigating from one page to another showing a dialogue stuff like that not any UI stuff so I cannot do it over here and we know that blog Builder is the one that renders the UI on the screen so we can keep this block listener over here but after that we can also use the block Builder so I can just wrap the single child scroll view again with the block Builder widget and now again I'll have to do the same thing all block all state and here I can just check if state which we again get access to over here is au loading if it is off loading then I want to return a circular progress indicator and I also want to center it so I can just wrap it with a centered widget nice now I can just restart the entire app and see if it works so I'll just do rrmail.com test 1 123 I'll click on sign in you see we get the loading indicator and then we move to the next page brilliant but don't you think there's a problem with this code in bigger apps literally almost all the screens will have conditions like this where we'll need listener and we'll need Builder as well so we can't keep on nesting stuff again and again because this is so much code to write instead of using block Builder and block listener nested together what we can do is use something called as block consumer which is basic basically the combination of blog Builder and block listener that would reduce a code by a lot and would perform the same actions block listener plus block Builder would do so instead of using block listener and block Builder what I'm going to do is again just copy this code so that I don't have to rewrite then then I'll just remove the blog Builder code from here yep so blog Builder is removed now now instead of using block listener I will use block consumer and we have our listener which I'll keep at the top then after that we'll also have a builder and in the Builder we can have context State that's it and then I can paste my stuff if state is off loading then I want to display a loading indicator otherwise I want to display a single child scroll View so let's remove the child and return a single child scroll view so this is our entire code now we can just use block consumer now it would have a listener and it would have a builder and it would build stuff accordingly we don't need a child widget anymore now I can run restart the entire app I'll have rrmail.com test 1 2 3 I'll click on sign in it goes to the new page it works just as before the only difference is less boiler plate code now so just to recap block consumer is basically block listener plus block Builder block listener is used whenever we want to move from one page to another in response to a state or if you want to display a snag bar if we want to display a loading indicator instead we would be using block Builder because block Builder has the capability to return the UI so I hope that's clear now the last thing for this is I want to display stuff over here so I want to display the uid of the user in bigger apps you might have the user model so you might want to display the name of the user and stuff so I'll just display the uid followed by that I will also create log out event and just log the user out so I can just go to the home screen and now how do I display the U ID of the user to display that I can just get access to All State right if it's a success it would give me the user ID so I can just use the OD State and as we know we can use block Builder so that we can display the UI but there's one other thing you can use instead of using just block Builder and that is using context do watch now you might know this from provider but context. watch basically always keeps listening to any changes in the state in a particular Pro provider so I can just pass Au block over here and this way I'll get access to the state and that would be the O State now I'll treat this o State as o success because the only way to reach the screen is if the O is Success so I can just do body as Center child text of au state. uid and that would be enough for me to display the user ID of the user so I can just do rrmail.com the password could be test123 I'll sign in and there we go we see rrmail.com followed by test123 which is our user ID and instead of using block provider you could also use this but the only problem by using context. watch is that this app bar will be rebuilt as soon as the state in O Block changes so if there's any state change in O Block this entire scaffold will be rerun as a result of which unnecessary components will also be rerun so if you want to avoid rerunning or rebuilding extra components you might want to use block Builder but I'm fine with that right now I can just use context. just to demonstrate that you can also use this along with blog Builder now the final thing that I want to do is just add a log out event so before that I'll just create the UI I'll do a very simple thing I can wrap my Center text with a column and followed by that I can just use a gradient button and I understand that the gradient button will say login but I'm not going to edit that out this is not a UI tutorial just consider consider this button as a sign out button all right now let's go to Au event and create a new event which is O logout requested and we can extend that to off event now we don't require anything from the Constructor in this case because when a log out is pressed we don't have to do anything we don't want to get the user email we don't want to get the user password nothing so our event is now created I can just go to O block and here just create another event handler which is on o log out requested so once that is done I will get access to event I'll get access to Emit and based on that I will log the user out so I can again just do try catch e and I will emit or failure just in case some unexpected error occurred and over here first thing I'm going to do is again emit Au loading so that we tell the user that the loading is happening and after that I want to just do this right I just want to use async over here and then I'll await future. delate duration of 1 second and we'll emit well OD success no OD success is when the login is successful so I can not pass that in because I don't even have the uid of the user anymore what I do need to do is again send back to the O initial State o initial was the state that was present initially so we'll again come back to O initially there's no error there's no success so we just come back to the home screen as simple as that now I can just go to the home screen and in the onpress I can do context context. read note that I've used context. read over here instead of context doat context doat continuously watches the state change context. read is a onetime event and after that I can just do Au block then I can add an event and that would be Au log out requested event simple enough but once this happens we're not automatically going back to the home screen right so we need to make that happen as well and we'll be using block consumer for that we want to display the loading indicator we want to navigate from the home screen to the login screen again so I can just WAP this with a block consumer pass O Block over here and in The Listener I can do one single thing if state is au initial that means I need to go back to my login screen so I can just do Navigator Dot push and remove until and then I can go to material page route Builder would be the context and we would just return a login screen so after this is done we finally want to display a loading indicator so it can be if state is au loading then I just want to return a centered circular progress indicator so this is the same thing that we have done before and just restart the app can just do r at the gmail. password will be test 1 2 3 I'll click on sign in I'm signed in now this is a sign out button so we can click on sign out and we get an error over here the reason we get this error is because it expected a value of typo success but CAU one of typo initial the reason is pretty simple here we've done as OD success and then later on on our state becomes o initial so it's treating this as o success but it's not actually o success it becomes o initial so we cannot put this line over here instead we have to put that line over here right now this should work and actually since we've already used block consumer which is a mix of block Builder and block listener I can remove this line and instead just use the state to use state do uid and I can just do state as o success. uid now I can try to restart my app and see if it works I'll just do this followed by test one to 3 click on sign in here I come I'll click over here and I go back to the normal page so earlier we got this error because we were treating State as OD success but we had clicked on the sign out button which changed the state to O initial so it was no longer o success it was O initial and we were treating it incorrectly because of which we got the runtime error so with this we have completed the entire form validation and logic of our code so this app is completed but there's more to block that we can explore so the first thing that I want to explore is if we just go to O Block do dot I just want to let you know that this function can be removed out so that you can write cleaner code right now everything is just put in the body of the Constructor we don't want that we can make this code cleaner by taking all of this outside and putting them in a separate function of its own and that can be done over here I can just say this is void on o login requested and notice that I've created this as a private method so that this function cannot be called outside of this block and after this I can just paste everything else awesome now I can just take this on not login requested and put it over here this makes a code much neater I can do the same thing for log out requested as well so I can just create void on Au logout requested and paste the same thing over here and then I can just take this and put it over here so this makes our Constructor the body of our Constructor very clean and with this we also know what all function handlers have we created and if you want to go to a specific one we can just go to that and see it another thing is we are getting an we getting a warning over here mainly because we have passed event and emit over here but we have not specified the type to do that we can just type in over here or login requested because that's the event that we're catching over here and the emit can be emitter and the type of the emitter is going to be Au State all right there we go and we can do the same thing for on or log out requested as well so just paste it over here and there we go but yeah instead of using Au login requested we have to do Au logout requested and yeah so the warnings go away and our code looks much cleaner now so that's one Improvement we could make the other Improvement is not exactly an improvement but it is the features that block offers in Cubit we saw that block that Cubit used to offer a lot of functions that we could use for example on change on change was used just to track the changes that were made so I can you do the same thing over here by Printing and saying this is the O block and the change that occurred is dollar change all right and we also know that on error exists so we can just use on error as well but we don't have any error and you know how to create error so I'm not going to dive into it so we can just remove this temporarily now I can just restart my app I'll open my terminal I'll first pass in an incorrect password that's just four characters and then I'll click on sign in it says password cannot be less than six characters and the change here is first there's instance of for initial which goes to loading as a result of which we see the loading indicator but instantly after that we see that o loading changes to O failure because the password was less than six characters long if we type in the correct password and I'm just going to remove everything from the terminal again I'll click on sign in you see we get Au failure to Au loading and from o loading to Au success and that's how it goes so that was on change another method that's present on block but that was not present on Cubit was on transition this method is not present in Cubit you can try it in the to-do list code it's only present on block block and I'll explain why it is just present on block but first let's just print what we're getting over here the transition so we can just print the transition over here and see what we're getting so I'm just going to format it in a similar manner so we have or block and we'll put in the transition but along with that I'm also going to say this was transition and this was coming from the change method all right now let's see what the difference between the both is so can just do R gmail.com again and there we go but now you see we have transition happening over here which occurred before the change so transition was called before on change was called so the current state is instance of au initial and that's to be expected that's the initial State and after that the state becomes all loading that's very similar to what we see in change right change gives us Au initial and or loading but the thing on change doesn't give us is this event this event is telling us because of what event did this transition of State occur what was the reason behind this CH State changing that's what we get to know because of on transition since o login requested was called Au initial was converted to O loading similarly o loading was converted to O success because of O log and requested those are all happening because of the same reason because Au login requested was clicked on and in change we cannot see that and the reason on transition is only present in Block but not in Cubit is because Cubit doesn't work on in events it only works based on what function was called block works on the basic concept of events that's why we get to know what is the reason because of which the transition occurred so I hope that was clear and and this event part that on transition gives us is very useful sometimes because there could be many reasons why the application State could change from the user being authenticated to unauthenticated so if the user clicks on a log out button they could go from authenticated to unauthenticated but another reason could be that the user access token was revoked and they were forcefully logged out so with block we are easily able to see what because of what event did this change occur and that extra information can help in some cases and in those cases it's necessary to use block instead of using Cubit another area where block can shine is when we want to add Advanced Event Transformations so when you want to take advantage of reactive operators like buffer debounce time throttle Etc that's where we can use block and that's where we cannot use cubid so for those who don't know let's say debounce what is debounce debounce is a way of delaying the execution of a function until a certain amount of time has passed so for example if we have a login form we don't want to allow the users to click on the signin button like a 100 times within 1 second we want to stop that because if the user clicks on aign in button 100 times in 1 second that's not really a user that is a bot and we want to not allow that this might seem insignificant in our app but let's say we were building a search engine in a search engine if there are 100 inputs given in just one second that's a bot and we want to disallow the bot to do that otherwise that would be a lot of resources and a lot of database reads calls that were made so that's where block can help us as well to know more about these event Transformations and what you can do you can check out another package called block cont currency which we can use to create such reactive events so just to give you a clearer understanding and a clearer summary block is usually used when you want to take advantage of event Transformations then you want to take advantage of on transition so you want to know what event caused a particular State change but if you don't want to do any of this then you can just use cubit because Cubit is very easy to use you don't have to create events you don't have to put much effort into any of this boilerplate code you can just create your function and get started now the last thing I want to cover is not about block or Cubit it's about another thing that block package gives us access to which is block Observer now you know in Block we can override the on transition and on change functions and that would work fine F but what if we don't have just one block we have like 100 and 200 blocks created do I have to write on change and on transition for every single one of them that would be pretty cumbersome to write and I don't want to do that let's your case arises where we want to change the onchange part we have a pretty standard way of printing everything but let's say we decide to change the format in which they're being printed so that we can understand it more nicely L do I have to go in those 200 blocks and change them every single way instead of doing that can I have just one centralized control that's where block Observer comes in play so what I'm going to do is just minimize this uh in the lip folder I'm going to create a new file called app Block Observer do Dot and here I'm just going to create a class AB block Observer that does nothing but extend sends a block Observer which comes from the flutter block package and here we don't have to override anything or do anything necessarily however we do wish to overwrite certain methods which is first on create which we can do so whenever a block or a cubit is created we can get to know they were created so we can just print them over here so I can just do block so that I get to know what was created so after we've done this we need to register this app Block Observer somewhere right now it's just a class that was created but it's not called anywhere or registered anywhere so let's go to the main. do file and at the top we can just do block. Observer is equal to app Block Observer once we do this and put an equal to sign I can just restart my app and there we go we see instance of O Block created because we've printed a block over here that tells us that a block was created now to give more specialized messages we can do that we can just say block. runtime type that tells us what is the type of the block that was created and we can also say that this was created and obviously if you want you can just print more information like block. state which tells us the initial State as well but right now I'm just going to do this much and let's see what we get I'll just restart my app and you see O Block created no other block will be created so we don't have to do anything else now let's look at other methods that are offered we can use on change and we know what on change does we can just print the block so what block was there and what was the change that occurred in Cubit there was only change that was given to us but this is an improvement in Block Observer because we also know need to know what block was changed right so we can just do block which tells us which block was done and we can say changed dollar change simple now I can just restart all block was created now I can just do this and click on sign in and here we see transition being displayed that transition is being displayed because of O Block that we've created over here so we can just comment them and let's retry again I'll quickly log in and there we go we see instance of all block changed it changed from this to this then this to this the benefit of this is if we have multiple blocks now I get to know every single time they're changed and that's a really good thing we can also do this for on transition we can also do this for on error for everything all right so you can try this stuff on your own this is a nice thing to have in your app if you want to keep track of the changes it helps in debugging a lot so that's all I had for block and cuit now finally let's get into the weather app where we implement the block pattern using block State Management so the final app that we're going to work on is the weather app to continue along with me you can find the link to the beginner files in the description below you can clone the repository and after you run it it should look something like this this data that you see all the data that's present over here is coming from the open Weather API so this is the main temperature in London right now it's coming from the open Weather API this is the AL forecast and there's additional information about humidity wind speed and pressure to dive into the code we can open the lip folder and as we can see there's only one screen over here which is the weather screen this weather screen not only contains the UI but also the call to the API over here so everything is set up in just one weather screen file so it gets the current weather then we call that get current weather and we display it on the screen we also extract the data over here in the build function so that we can display it on the screen there's separate cards created for allly forecast and additional information which you can find over here and here the secrets. contains the open Weather API key and that's all there is to this app now what is our objective with this the objective is to convert this messy code into a systematic code using the block architecture and we'll also be using block State Management to do so to get started first we must understand what is block architecture overall this diagram that I have encapsulates this pretty well first there is the UI screen UI screen communicates with the block how does it communicate well UI screen sends something known as events to the block and we already know what events are there are certain inputs that can be given in the UI screen let's say when a button is clicked or something like that or even in some life cycle method for example in inet state so UI screen sends events to those blocks the block that then communicates with the repository to understand repository we must first understand network provider repository sends a call to network provider now what is this network provider this network provider is basically your data Provider by data provider I mean in the weather app we're communicating with the open Weather API right now we need that open Weather API raw data that we have so network provider is just going to send the call to open with map API and based on that I'm going to get some data and that data is going to be raw data so network provider just gets the raw data then it sends the raw data to the repository once repository gets the raw data it handles that data how it converts the raw data from whatever form it is let's say a string to a form which would be a beneficial developer EXP experience for example it would convert this entire thing to a weather model in our case so it basically takes a string and converts it into a model format and then it sends that model format to block after block gets that witha the model it just takes that data and sends it to the UI screen now in between there can be errors that occur and block handles that if there's an error block will correctly notify it in the UI screen and if there's no error then it will display it on the UI screen really well so that's how the whole flow goes I'll get back to this diagram after we complete the app but I hope you get a very basic understanding of what's going on so first thing that I want to do in terms of code is just take all the widgets and screen and put them in one layer so one important thing to note is that there are three folders that we can create the first one is the presentation layer this presentation layer is going to contain everything UI related it can contain screen it can contain widgets it can contain all of these things that are visible to the user then we have the block layer which we can just call it as a block layer and the third layer that we have is the data layer data layer contains everything related to our data because network provider provides your data from an external API to us and repository modifies that data handles that data and gives it to the block so both of them fall in the data category so let's create those folders the first folder that I have is presentation and in presentation I can have screens and I can have widgets now if you're using the feature first approach that means you're dividing your folders into features then you can have let's say say one feature and inside that you can have a presentation block and data layer of its own but if you don't know what feature first approach means don't worry about it you can just follow along like this so in this presentation layer I can pass in my screens so that should be fine and it automatically modifies my main do do file now I can take these two widgets and put them inside of the widgets folder and we get an error over here because these two Imports are incorrect now to make them correct we can just remove these two Imports go to the bottom import this allly forecast item and also import this additional info item there we go now if I just restart my app nothing really changes but now we've just organized our code a little better now after the presentation layer is done I want to work on the data layer I'm skipping block layer for now but we'll get to it later on first let's just manage data in data we have two parts repository which is this part and then network provider or I'm just going to call it data provider so I'm going to create a repository folder and I'm also going to create a data provider folder in this dat data provider folder I'm going to create weather uncore dataor provider do. file and this is going to contain a class called weather data provider and the task is very simple over here we're going to contain all the crude related operations over here so creating something reading something updating and deleting something everything is going to come over here and in our case we only need to fetch the data from an extern Al API so I can just go to my presentation screens weather screen and here I can just find my code for get current weather I'm not going to rewrite all of this so I can just command C and command V over here now I get the current weather from here but instead of returning map of string comma Dynamic I'm going to return a string and of course I need to import HTTP because that's the plugin I'm using to get data from an external API so I can just do import package HTTP HTTP do dot as HTTP once we do that we have HTTP with us and we're not going to specify the city name over here itself what we can do is remove it from here and ask it in the parameter so this is where the city name will come in handy the next problem is that open we API key is not defined so we need to import the secrets do do file after we have done this there's only one error that is the Jon decode but as I said we're not going to convert any data over here we're just going to go to the API we're going to call the API and whatever result we get we're just going to return that result so we can just do return result over here but result would just return a response so I can do response. body which would be a string if you want you can also do response. body Byes which would return a 8 list but I think body should be fine for me so the task of weather data provider is just to go to the API and return the string after we've done that we can go to the repository and create the weather uncore repository. file and again this is going to be a simple class which is called weather repository and here we're going to have a similar function implemented so I can go to my weather screen copy this line and paste it over here but now instead of calling the API again I'm just going to take this weather data provider and insert it over here so I can just do weather data provider dot get current weather and then I need to pass in the city name which I can mention over here or I can again take it from the parameter however we want I'm just going to keep it over here and move on another thing is if you're unit testing this function you don't want want to create instance of weather data provider over here you want to get it from the Constructor if you don't know about unit testing you can check out my series on testing as well but now considering that you already know what unit test is I can just take this weather data provider and generate a Constructor for it so I will generate the Constructor and there we go I'm actually not even going to require this this is just going to be a positional argument so once I have the weather data provider I can use that instance to get the current weather and based on this I will just get final weather data is equal to await weather data provider. get current weather there we go but now the function of the weather repository is to modify this data into an understandable format so I'm going to keep this code and what I'm going to do is use Json decode over here I'll take this weather data pass it over because essentially we getting response body right we're returning response. body from here so I can just take this response. body and replace it with weather data and then I can just check if data at this is not equal to 200 then we'll throw an unexpected error occurred but if that's not the case if the status is 200 then we do not want to return data because that's just Dynamic and we know it's going to return map of string comma Dynamic I don't want to return that what I do want to return is a weather model so I'm going to create my weather model first so in the lip folder I'll create a new folder called models and here I can create weather uncore model. file and then I can create weather model class but now what are the arguments of this weather model going to be to get that we can go to weather screen where we have extracted all of our data right I can just copy all of this go to wether model and paste that in so this is all the data that I need to convert basically so now that we have all the arguments with us we can just go ahead and put them in so we will have final double current temperature because the current temperature is a double value then final string current Sky followed by final double current pressure and rest of the things are going to be double as well so I'll quickly write them up and I'll see you after I've written them all right now that this is done I can just generate a data class for it right so I'll just generate a data class based on the do data class generator extension and there we go now I can just copy all of these things and paste it inside the from map function so that I can convert the data very quickly so for current temperature it needs to get this value for current Sky it needs needs to get this value from the API all of this was done in the flutter big notes tutorial if you're interested in it so we can uncomment current weather data put it as map and then take each of these values so I'll just take current weather data main temperature and put it over here the same thing for current Sky then the same thing for current weather data pressure the same thing for the speed and the same thing for youed now that we've done this we can just remove it and save this awesome now that weather model is created I can close this and go back to the weather repository now instead of returning map string Dynamic I'm going to return a weather model right and now I have access to the weather data which is a string so I do return weather model do from Json and then I'll pass the weather data over here alternatively you could also do from map and then pass the data over here and it would work fine and if you were confused about what's happening over here basically I created multiple functions like to map from map and all of those things but the main part is just the form map for us from map sorry what we doing here is we are taking in the map and we're just extracting data out of that map and returning a weather model from a map we creating a weather model that's all that's happening so yep that's how we do it we're throwing an error in case it occurs and then we returning a weather model if it's all good so I hope you've also understood the difference between the network provider and the repository in network provider we just went to the API and got the raw data and in repository we are just taking the raw data and converting it into a weather model and that weather model will be accessible in the block that's what we are returning now from this repository we're going to go to block so let's create a block over here in the lip folder we're going to create another one which is going to be a block so as we know to create a block we can just do command shift p new block and after that we can write weather as the name of the block then we need to select a location and the location is going to be in the lip folder only so I can select that folder and and there we go block has been created but one thing we forgot to do is add the flutter block package so let's add that dependency flutter underscore block after that is done we can remove these two Imports import the flutter block library and we also need to import the foundations dot dot line all right this came from the immutable so we had to import that as well awesome now let's start configuring our weather state so weather initial is already created for us and I'm going to keep that because as I mentioned in the login app as well whether initial is going to be the initial State there's no success there's no failure and the rest of the three states are also going to be very similar it's going to be final class weather success and that's going to extend the weather State then we are going to have final class weather failure and that's going to extend the weather State as well and then we have the final class which is the weather loading which will be extending the weather State as well so we have created all of our states and that's good now we can go to the weather event to create one weather event that we have and the one weather event we have is just to fetch the weather data so we can just say final class weather fetched because remember I told you that the weather event should be in past so we can just extend that to the weather event as simple as it gets so that's the one and only event that we're going to have right now in our app if you decide to expand this app further you'll have more events obviously now we can go to the weather block layer and here we're going to listen to one event and the event is going to be well weather fetched on weather fetched we're going to get event emit but we're going to create a separate function for them so we're going to have void get current weather then we get access to weather fetched event and emitter weather State and that's how our function looks so now I can just pass this get current weather and it should be a private one otherwise it will be accessible outside the block and we do not want that generally awesome now that we have the get current weather created what are we going to do in this block as I said this block is going to communicate with this repository they both are going to be in contact with each other so that means we're going to call the repository in the block itself and again if you want to unit test your block you want the weather repository to come from the parameter or the Constructor of the class so we can ask for weather repository from The Constructor now and this would be this do weather repository there we go and now we can call the weather repository do get current weather nice now this can be async as well we can aade this and we would get a final weather which would be equal to the nice weather model that we have and since this get current weather can throw we always want to use try and catch Block in the block as well so we can just go to weather block and here have try take this paste it inside catch e and then I can emit if there's a failure so if there's a failure I'll just do weather failure but it doesn't accept any argument does it so I can just go to the weather failure class just as before we're just going to have final string error then we're going to create a Constructor based on this so we'll create a Constructor and then emited the weather failure and I don't want this to be a required argument so I can just convert this to a positional one and now I can just pass e.2 string over here then we get the current weather and if everything goes well then we want to emit weather success but just doing weather success isn't enough we want to display the weather as well that's why in this weather success we're going to ask for the weather model so whenever there's a weather success I want to get get the weather model so we have final weather model weather model and then we can use click on the bulb icon and create Constructor for it and then here I can pass my weather model in so I know I rushed this part a little bit but just to explain it again whenever we fetch the weather this get current weather function will get called and this gives us access to the event and the emit function then we start the TR catch block and then here we say that with we want to get the current weather so it would be from the weather repository which would give us access to the weather model once we get the weather model we are just saying that I want to emit weather success with the weather model pass to it so that I can display it on the screen however if any error occurs then I can catch it and then emit a weather failure passing an e.2 string and one thing we forgot to do was emit the weather load loing event because as soon as get current weather gets called I want to make sure that we start loading the indicator and then if there's a success or a failure we're just emitting so it's fine so that's the entire thing for our blocks we can close all the save files I hope you've understood it now we can just go to the presentation layer and start removing all the unnecessary stuff so for example we don't need this part we don't need to call get current weather we we don't need the weather future instead over here we're going to use block provider to call this particular event the weather fetched event so for that first I need to register my block as well so to register the block I can just go to material app and then wrap it with a widget called block provider and here I'm just going to call it weather block so make sure we import flutter block block and the weather block files after this we need to pass in weather repository to pass in a weather repository you might think we can just do this but there's a better way that block provides to us and that is if we just wrap block provider with another widget block provides us with which is repository provider so we can use repository provider which has a very similar layout as a block provider but instead of returning blocks we need to provide repositories over here so we can just use create context and then we can pass in the weather repository now weather repository requires weather data provider so we can just pass the weather data provider over here and now I can just use the instance of this weather repository in my weather block to do that I can do context dot read and then use weather repository like this so what I've done is above the block provider I've created repository provider something that blocks provides and here we can return repository related classes if you have multiple repository you can always use multi- repository provider which is also provided by block and in the child of this repository provider we have the block provider where we are returning a weather block and doing context. read weather repository so we get access to this particular instance of weather repository nice now I can just go to the weather screen and use context do read which comes from the flutter block library and here I can pass in weather block then I'll use dot add to add an event and my event is weather fetched all right there we go so in the init State as soon as we start the app we use context. read. add weather feted to get the F uh to get the weather and as soon as we add this weather fetched event our weather block will run and it will catch this and it will start executing this function and as we know this would go to the repository repository would go to network provider and everything would happen now we can remove the non-essential functions I can just comment this out we'll not be using future Builder anymore because we don't have a future to handle anymore we've already done that in weather block we've already got our data and all we need to do is display that data so instead of future Builder I'll have block builder then obviously in the block Builder I need to mention the name of the block which is the weather block and the state of the block which is the weather State and in the Builder you're going to get a state not a snapshot and since this is not a snapshot it's a state I can just comment this line I can also comment this line and then we have all of these variables we're going to keep these variables but we're going to extract the data from the state but before that we have we have to handle the loading state right if there's a loading State we don't have any data so even if we do anything it would just give us errors so here we can just check if state is not WEA success so if it's not a success then I just want to keep loading forever so I can just take this and paste it over here now I can remove all of these lines I don't care about them anymore so if state is not a weather success it would keep on displaying the loading indicator but what if there's a failure right as still want to display the error text so for that we can just handle that case so if state is weather failure then I want to return a constant Center child text saying State DOT error and it's not a constant because we using state so we can remove that constant and there we go make sure this if statement is before V success otherwise it would just keep loading forever because weather failure is not a weather success so this condition would be true and as a result of this this circular progress indicator would keep on showing up but anyways if there's a failure we show an error if there's no success that means it is just loading so we display a circular progress indicator otherwise it's going to be a success and that's why I can just extract the data from here my final data is going to be state DOT weather model and that correctly analyzes this because we've already checked the condition that it's not a weather success if it's not a weather success this would happen but if it is a weather success that means we're only going to get the weather model and that's why we get the weather model now we can use that to get all the data so I can just remove this current weather data it doesn't actually contain any data for us then I can take this data and do data do current temperature that will give me the temperature and the same for all of this I'll do data do current Sky data do current pressure data do current wind speed and data do current humidity and because of this all the errors over here will not be there and the final five errors are in this early forecast and I'm not going to complete this part I leave it up to you if you've understood the sture you can try it on your own and see if you're able to do it it's a very similar logic we've already got the weather data provider with us we're already getting the weather repository we're converting it to from map so we can just pass in the arguments over here and see how to get all the early forecast item stuff over here so I recommend you to try this on your own but I'm just going to comment this out and see if the block layer worked successfully for the rest of the things let's also remove the unused Imports at the end we can see if it worked so let's get it and we do see the temperature over here with all the additional information if we try to run this this doesn't work because I commented this part over here so let's implement this as well so whenever this refresh icon is well run I just want to call the API again so I can just take this and paste it over here and now if I run this you see I see the loading indicator once that's good now just to verify that everything works properly I'm going to go to the weather repository and instead of London I'm going to put New Delhi and see if that works so I'll just restart and there we go we see 291 with everything correct as it should be and this is the weather app implement using the block layer now just to get everything in place I'm going to explain this block pattern using a current code so I'm just going to start from the ending first we implemented the network provider which was our data provider over here and we got the current weather it was in the Raw data format it was in a string format we didn't manipulate the data in any way we got the data from an external API we just took the string part of it and returned it to repository so repository got a raw data now what repository is going to do is convert that raw data into a data that would be helpful to us and we did that by creating a weather model once we created the weather model we called the weather model. fromom map function because of which we were able to return the weather model to our block layer now the data that we would return could also be map of string Dynamic and that would be fine as well but I think weather model is a better way of doing this because we get Auto suggestions when and wherever we need so it would be less error prone and would result in a better code quality overall if there's an error it also throws an error so if it throws an error that also goes to the block and the block can then display it on the UI screen for example if I go to weather repository and actually weather data provid Ider and mess up the URL a little bit let's see I'll restart and you see it shows an unexpected error occurred and this shows up because in the weather repository we're throwing an error if the status code is not 200 so it shows this error message and that's what we were returning to our block and we know what block is finally I can tell you what block means block basically means business log IC component so block is basically managing all the business logic of our app in Block we basically send the input so UI screen is sending an input to a block right it is from the init state of our UI screen we are saying that as soon as the screen loads we want to send some data or some input to a block and that input is an event based on this event we will get data from the repository and the repository would get get it from network provider then it would manipulate the data it would send it back to block and now again block is managing what should be displayed on the screen so it's managing the entire business related logic of our app it decides when to show the loading indicator it decides when it is a success or when it is a failure and the UI screen at the end is displaying everything it is displaying the widgets it's displaying the screens it is displaying the entire layout but block is the one that is deciding what to show so I hope you've understood this entire block pattern and I also hope you've understood things about block and Cubit I've not used cubid in this one because I thought let's just use a complex example so that people following in Cubit would also be able to follow now I understand some of you might think why we got to put our code through so many layers it's just making a simple app more complex and you're right it does make a simple app look more complex but what if the simple app became complex the app starts to become complex when more features and more Engineers start working on it word block offers is separation of concerns testability and scalability by separation of layers I mean every layer has a well- defined unique purpose and all of them do not interact with each other for example block can interact with the repository layer it cannot interact with data provider layer because of this we get Sav from a big mess the code could potentially become so this was it for the tutorial thank you so much for watching and I'll see you in the next video
Info
Channel: Rivaan Ranawat
Views: 12,862
Rating: undefined out of 5
Keywords: flutter, flutter tutorial, flutter tutorial for beginners, flutter bloc tutorial for beginners, bloc tutorial, flutter bloc tutorial, flutter bloc explained, bloc explained, flutter bloc project, flutter bloc, flutter bloc pattern, flutter bloc pattern tutorial, flutter bloc architecture, flutter bloc architecture tutorial, flutter bloc app, flutter bloc package tutorial
Id: SDk_GldOtK8
Channel Id: undefined
Length: 154min 21sec (9261 seconds)
Published: Thu Nov 30 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.