Flutter x Clean Architecture
Tags: flutter, dart, cleanarchitecture
Published: 2022-06-30 01:50:42

> In the scope of this article, I assume that you already know what Clean Architecture is, and why should we use it.

## ./ Flutter Clean Architecture

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/68zk6fn6u38o7wzquncb.png)
As you can see, there are three main layers: **Presentation, Domain, and Data**.

> Role and description of each layer:

### I. Presentation
_There is no business logic processing on this layer, hence it is only used to show UI and handle events._

**1. Widget (Page)**

- Notify BloC of events such as screen display and user touch events, and Listen to the events emitted from BloC as well.

**2. BloC**

- Receive events from View and execute UseCase according to the event if necessary.
- Emit the data received from UseCase to View.
- BloC doesn’t know about View at all.

### II. Domain
_This layer is responsible for business logic._

**1. UseCase**

- Describes the logic processing required for the UseCase.
- Work directly to Repository.

**2. Translator**

- Convert the model into the entity in order to request to server-side, or convert the entity into the model to use for Presentation layer.

**3. Model**

- A model will not depend on the data that acquire from server-side.
- A model is used for the Presentation layer.

### III. Data
_This layer is responsible for communicating with server-side and data management logic._

**1. DataSource**

- Describes the process to acquire and update the data.
- This is the place decided whether to get the data from the server-side or use the data in the DB or cache.

**2. Entity**

- An entity will depend on the data that acquire from server-side.
- An entity is not used for the Presentation layer.

**3. Repository**

- The bridge between Data layer and Domain layer.
- We will use Translator in Repository in order to convert data.

## ./ Practice
_For a better understanding, I’d like to demonstrate a flow that receives an action from Widget, processes it, requests/receives data from the server-side, and finally displays the data to Widget._

> Source-code: https://github.com/dubydu/fluttourII


**1. Data Layer**

- Create an **Entity**.

{% embed https://gist.github.com/dubydu/f9ba8c8b7804bbd9c04e5116777b4420 %}

<br>

- Inside [api_client_type.dart](https://github.com/dubydu/fluttourII/blob/master/lib/data/api/api_client/api_client_type.dart), define an HTTP request like this:

{% embed https://gist.github.com/dubydu/bfce22c295c28061b555afff6dbc2c2a %}

<br>

- Then, open your terminal, and run this command: `make gen`, the [retrofit](https://pub.dev/packages/retrofit) will take the rest responsibility. You also can custom the command line by editing this [Makefile](https://github.com/dubydu/fluttourII/blob/master/Makefile).

<br>

- Define **DataSource**

{% embed https://gist.github.com/dubydu/24f7c3de6775f8ad3c0234e15ace9cd2 %}

{% embed https://gist.github.com/dubydu/6c2f22fef3fa1f67e1a53a019f86315b %}

<br>

- Implement **Repository**

{% embed https://gist.github.com/dubydu/24962a0af557d0a15910a4c7243c16c8 %}

{% embed https://gist.github.com/dubydu/a1edaf41679300d102745cd5c04b2122 %}

<br>

**2. Domain Layer**

- Create **Model**

{% embed https://gist.github.com/dubydu/d6a02fc4e3aa31edb46e8a1e5c9861c6 %}

<br>

- Define **Translator**

{% embed https://gist.github.com/dubydu/2822ab1ad1df41b12d6940a8bbae2796 %}

<br>

- Implement **UseCase**

{% embed https://gist.github.com/dubydu/b01762c86478069c9018ebbbf2495081 %}

{% embed https://gist.github.com/dubydu/e1a73d0183e5e8d625b23189080ef070 %}

<br>

**3. Presentation Layer**

- Define **BloC**

{% embed https://gist.github.com/dubydu/409b5ffb3f490a086c1f666f3d6ccebf %}

<br>

- Implement **Widget**

{% embed https://gist.github.com/dubydu/2539958edf958444590929b9507e8319 %}

<br>

**4. DI**

> Let’s make our code becomes more modular. 😎


- Create **config_module**

{% embed https://gist.github.com/dubydu/af47d9b7402414efc89694d38d25f7e8 %}

<br>

- Create **client_module**

{% embed https://gist.github.com/dubydu/96c70848de03b0f25885d1851175e2fe %}


<br>

- Create **datasource_module**

{% embed https://gist.github.com/dubydu/ae290b8f403c6e0e57c9059b6c6310f0 %}

<br>

- Create **repository_module**

{% embed https://gist.github.com/dubydu/1ca86b3d6503f4dc057305a95c5de82c %}

<br>

- Create **usecase_module**

{% embed https://gist.github.com/dubydu/7877dd013225f7b2516dbd2d771ad93e %}

<br>

- Inject UseCase to BloC in [my_app.dart](https://github.com/dubydu/fluttourII/blob/master/lib/my_app.dart) by conforming to all of the modules.

{% embed https://gist.github.com/dubydu/b3907a36c5f6a80794b83319d2f07b51 %}

That’s all, run the project, and let’s see what happens!

<br>


### Pitfalls

In order to run this project, you need to run in a specific environment.

Development: `flutter run -t lib/main_dev.dart`
Production: `flutter run -t lib/main_prod.dart`