The Software Engineering approach in Cross-Platform Programming with Flutter (Part 3)

Ali Yazdi
Flutter Community
Published in
7 min readJan 26, 2021

Designing and developing the Flutter application data models and backend using the Build value and Bloc pattern.

This part continues the previous part. If you haven’t read from the first part, go to this link, or if you haven’t read the second part, go to this link, then come back here.

Software Engineering with Flutter (Part 3)

In this part, I will elaborate on how to build and develop services, Blocs, models, and some other cool stuff as our features.

The Gallery Models

We need to be able to use the models as an immutable object and easy to serialize and deserialize them. Using an immutable object has many advantages. So I’m going to use the build_value package to do so. You can take a look at this article to learn more about that.

To build your application models, you have to take a look at the class diagram that I talked about before. Before building the models, the application class diagram should be verified by your backend team.

Let’s see the gallery models. I hope you opened the first part and checking the class diagram. Some of them are obvious, like Account, Authentication, Gallery, GalleryQuery, Media, MediaType, and Album.

Authentication Class
Authentication Class

The authentication class can be split into Login, LoginBody, Register, and logout. For example, The Register and Login models look like this:

Don’t forget to install the build value snippets plugin on your editor. It helps you to prevent writing build value boilerplates on your own. For example you can create your model file with its model name and then type `bvtsf` to generate all of its code, and at last create your properties of your model.

If you want to get a serializer for this model, you should create serializer.dart in its models directory like this:

Then all thing you have to do is running the build_runner in the authentication_service directory by these commands:

$ cd services/authentication_service/
$ flutter pub get
$ flutter packages pub run build_runner build

Now you’ve got your authentication models ready to use. You can do the same steps for other services.

Some of the models you might not understand are the exceptions for the HTTP requests and the responses' pagination.

The HTTP exceptions are useful when we’ve got the not ok statute code for the request, and we can throw the HTTP service by these models. The HTTP service will be explained soon. The pagination model is useful if we paged our response, like the gallery's images and videos. I think the pagination model is the most tricky, and it looks like this:

And it can be used as Pagination<Gallery> if the Gallery response uses the pagination.

The other models of services look like the sample. You can check other services and try to practice and code some of them on your own.

The Gallery Blocs Layer

The most important section of development relies on developing good Blocs for your application. Before explaining the gallery Bloc, take a look at the Bloclibrary documentation and make sure you understand the core concepts. Let’s create a good Bloc for the authentication service.

Each Bloc has three segments: Bloc, Event, and State. Events should be defined in the Event class, and states should be defined in the State class.

  • For each event that happens in the UI, the UI tells the Bloc with that event.
  • Bloc is responsible for getting that event and changing the application states.
  • In this transaction, data might have been changed, and with each state change, we might have a new build.

Let’s see authentication Bloc:

Make sure you add the equitable package. Equatable is an abstract class that helps you implement equality without needing to explicitly override == and hashCode.

We need to tell the Bloc package when the state has been changed and rebuild my UI, so we use it in the State class and add the properties that cause the state to change.

Steps to produce Bloc:

  • The first thing you need to do is to define your state and status. Unknown, Authenticated and Unauthenticated are the states of the authentication service. If the authentication happens, an account must be saved. Put state functions in the state and extend it from equitable class, then override props and put the properties you want to differentiate between states. We will use this ability in the UI.
  1. The events should extend from an abstract class that extends equitable. So I made AuthenticationEvent and the AuthenticationStatusChanged extends of that.
  2. The last thing is defining the Bloc class and overriding the mapEventToState method, mapping the event, making your desired functionality, and changing the state by yielding the new state. I separate the login action from the authentication because the authentication can happen anytime. However, the login just happens when the app start and the user has been unauthenticated.

For the other Blocs, the same thing should be considered:

Defining the Bloc states -> Defining the Bloc events that happen in the UI -> Defining the Bloc map events to states.

The Gallery Data Layer

As we planned, I’m going to split this layer into the repository and the providers for each Bloc. Let’s take a look at the authentication repository:

As a Bloc, I want the repository to give me the login or register model. I don’t want to know how it is going to do that. The responsibility of giving the login or register model by any means is for the authentication repository.

The authentication repository first could ask the storage provider for any authenticated account if the storage doesn’t have one, then the repository calls the API provider, and the API provider calls the HTTP service and provides the account login or register model.

I haven’t implemented the storage provider yet, but the API provider looks like this:

I will explain the HTTP service later, but we just know that we need to pass the URL and method and the body and then get the response body from it if the HTTP exceptions have not occurred.

The Gallery Presentation Layer

Finally, this is the layer all things come true, and we can see the efforts that we made.

This layer is located in the lib/presentation/screens directory. We have a separate directory for each screen we want to make, and the general widgets should be located in the lib/presentation/widgets directory.

What is happening between layers in a nutshell:

  1. Something happens in the UI.
  2. UI tells the Bloc with the defined event.
  3. Bloc observes that event and requests its repository for data if needed (If Bloc doesn’t need the repository, go to step 7).
  4. The repository asks the provider to provide the data.
  5. The provider uses specific services that collect the data.
  6. The data return from services to the provider, then to the repository, then to the Bloc.
  7. The Bloc changes the state with data if needed.
  8. The UI that is observing the state changes rebuilds itself with the new state data.

So in order to do that in the UI layer, we should define them in reverse. It means that the RepositoryProvider should be the parent, then the BlocProvider should be the first child of the repository, the BlocListener is the widget for the UI listening, the Bloc should be the second child, and in the end the UI should be the last child, the hierarchy looks like this:

RepositoryProvider(optional) -> BlocProvider -> BlocListener -> UI
Authentication Activity Diagram

In this layer, you have to connect your presentation layer to its Bloc while you are checking its activity diagram. Make sure you are building the widgets like the above sequence. For example, the authentication presentation looks like this:

I eliminated some unnecessary codes. As you can see, authentication is one of the most important widgets and should be the parent of the rest widgets, and if the user credit has been expired, it should handle the new state for that situation and navigate the user to the login page.

Authentication Service Full Structure

Let’s see what the outcome of the full structure of the authentication service is:

This is what you have to create and build for each service that needs the Bloc and data layers. The Bloc, Models, providers, and the repository.

Final Words

Congratulations, at this point, you understand how to make a good application. Some many features and services remain to explain as we planned. Testing and deployment phases are going to be the next article subject. The features and services will be covered beyond this series, so stay tuned and tell me what’s the best gallery feature needs to cover first.

You can check out the gallery repository, but I recommend you not to clone it. Please make your own repository and try to do all steps on your own and then share your repository with me or others in the Flutter community. And make the best community in the technology world for Flutter.

Thank you for reading. I hope you enjoyed it. This article takes me so much time researching and developing in both software engineering and flutter programming, so if you found this article helpful, please clap and share this article. If you have any suggestions to make this article better, don’t hesitate to contact me or write a comment down below and I’d reply to you fast if I weren’t asleep.

Follow Flutter Community on Twitter: https://www.twitter.com/FlutterComm

--

--

Ali Yazdi
Flutter Community

A Flutter lover for two years. A CS graduate interests in using Artificial Intelligence and Software Engineering in my work. An open-source developer.