My Flutter recipe
Over the last few years of playing around and experimenting, I have done my fair share of failed projects and junk code. One might even say I’ve learned a thing or two. Now, this won’t be a tutorial or a flutter guide, it will be more like an “I have done these things and they work for me” blog. Also, I’m assuming you have an idea of what flutter is, what BloC & Cubit is, and some general programming knowledge.
How I found the recipe
I have played around with the more mainstream state management solutions out there for flutter and I have found that if you’re coming from a state management-less background you might agree that they are confusing and difficult to grasp, but when you do, it's like euphoria.
I found that BloC & Cubit suits the flow and processes of flutter the best.
BloC or Business logic components is a design pattern that allows you to separate your business logic from your screens to help with those frames and load times. Cubit ties into it to create a beautiful tool that separates your business logic from your screens and manages the state too.
Therefore your concerns are definitely separated.
So now that we’ve established what bloc and cubit adds, in comes the recipe.
Let’s say you have an API that returns a user, this user has a name, a surname, and an email. You could keep it as a JSON string and lose your mind along with the build context, or you can create a model (or object) that looks like the return. Add a fromMap and toMap to the mix and you’ll be good (this will make sense later).
Create helper functions
Helper functions are your main workers, they are the stage crew with the black shirts. Here all your API calls and some business functions will be done. The helper function in this scenario will make the get call and receive the JSON response as a JSON object; you should decode that into a map (a map is a key-value pair object in flutter), this is where the fromMap comes in. This translates the JSON object into a flutter object so that you can use it as you would a normal object. Now return this object.
Create cubit methods to expose helper functions
Create the cubit methods that will use the return from the helpers to either change states, save the data in the state or just run a function. Cubits are very important for all of this to work. My recommendation is to have a loading state, a loaded state, and an error state at the very least. A general cubit method will work like this: gets called > emits a loading state to show a loading indicator or something > runs functions and does things > emits a loaded state if the desired outcome is achieved, or an error state with a nice error message otherwise.
Here is where you create a bare-bones screen Don’t worry about those pixel-perfect paddings just yet, just throw together all the components you’d need to create the desired functionality. Wrap that scaffold in a blocBuilder to add the cubit into the BuildContext and start implementing your fresh cubit methods.
Change screen depending on the state
Here is where you add the salt and let it simmer. Add your cubit methods into your screen and do a test run, make sure it works, add if-statements in the build method to show an error message if there is an error state, a loading indicator when something is loading, and the screen shows when the state is loaded.
Now you get to plate the dish. Here you can add the styling and get that screen looking pixel-perfect, and run through the functions again as a good measure.
And boom! Now you are on your way to a great scalable, robust, and maintainable project that will turn some heads when you show the performance stats.