When using BLoC as the state management technique for your Flutter app, your best bet is to open a folder called packages and put all of the code for all of your BLoCs into it.
BLoC in Packages Folder
I’ve got this idea from Felix Angelov and it serves me well. Previously, I had bloc code in folder blocs, screens using it in ui/screens, repository for data in /repositories, models in /models and so on. The idea of blocs in packages folder is the opposite: act as if you were really creating a standalone package for someone else to use, like you were going to publish it on pub.dev.
The image above shows a mix of blocs in their own folder /blocs and the blocs that are in the /packages folder. The former are the legacy code and they are being transferred to the /packages architecture.
Basic BLoC Structure with Models
The basic blog will be the same regardless of the encompassing folder. In the image below, we see a Login bloc with models for email and password.
There is not much code for this bloc at this place as the rest of it is dispersed throughout the entire app. This becomes error prone and tiresome after you have a few dozen of these to handle.
Structure of Specific BLoC Files in a Package
Now let us see what does a bloc within a package look like:
A much better approach, I must say. Everything is tucked away in its own folder or subfolder; if you do not want to see it, it easily becomes invisible.
This approach favors really small pieces of code. We will show on screen only surveys_screen.dart, and here is what its code looks like:
Notice that the screen that we want to show, SurveysBloc, is within a BlocProvider. It provides the environment for the actual form on the screen, which is in SurveysForm widget.
Also note that even a very small widget such screen title gets its own file and class SurveysAppBar in surveys_app_bar.dart:
If you were wondering what does the app or the above code do, here is the screen it produces:
The exact functioning of the bloc code deserves a blog post of its own, so let us now turn to the additional structure of the app.
The UI Folder — Graphics Elements on the Screen
User Interface elements get their own folder. There will be, typically, three subfolders in it:
screens | The majority of your apps files will be in these folders. |
themes | Usually, there are three or four files here, one for themes in general, the others to specify the concrete values for the theme. Using themes with blocs is extremely easy, once you set it up, you can forget about it and still have it working like a charm. |
widgets | The heart and soul of Flutter, the widgets are small parts of screen property that are neither very complicated nor long. Not a full blown class and not just one line of Text. Good candidates for widgets are app background, button text style, customized buttons of all kinds, euro sign, avatars and so on. If you use the same widget in two places in the app, put it into its own file and place into this folder. |
Structure of Screen Folders
Here is what a typical structure of screens files looks like:
The widgets specific for the Welcome screen are WelcomeText and NewText so we place them here, in the /widgets subfolder. Notice that there is a /view subfolder beneath /welcome and that there is /widgets beneath that /view. It is granularity once again — if you are working on the Welcome screen, you will find all of its files in one place and if not, you just look at the closed subfolder and scan on to something else to fix.
The utils Subfolder
The utils are the files that are not widgets — that is, have no presence on the screen, but still have some useful function. Basic examples are delete keyboard, dio logging or hex to color conversion. You can also use utils to convert latitude and longitude to string, control input data with regex, create a singleton and so on.
Here is what it looks like in a larger app:
These are the main parts of a Flutter app structured around the BLoC pattern. Code is taken from one of my apps I create for customers. If you want your app to be structured in this way, please contact me here or on LinkedIn.