Multi-packages Clean Architecture in Flutter — Data layer
This article is part of a series on implementing a Clean Architecture with separated packages.
In the previous article, we’ve seen the domain layer that defines repositories interfaces. Let’s see how to implement them!
The data layer can be pretty vast as it can contains very various implementation details. Here are a few examples:
- API calls
- Local storage (database, file, shared preferences, etc)
- Caching strategy
I won’t go too much into the details on each file in this layer because it is pretty straightforward but I will quickly the call flow of the data layer:
- The entrypoint of the
datarepository is the repository implementation (remember, the interface lives in thedomain layer) - A repository method will usually call an API or a datasource to get requested data, doing any deserialization operations that might be needed. At this point what we call the “data” is a model defined in the data layer, but it’s not yet the entity asked by the repository interface.
- [Optional] Depending on the strategy the repository method can choose to cache fetched data at this point
- The data model is converted to a
domainentity and returned to the domain.
Here is an example of what I’ve just described with the implementation of the CoursesRepository from the demo app:
@Injectable(as: CoursesRepository)
// 1️⃣
class CoursesRepositoryImpl implements CoursesRepository {
final UserDataSource userDataSource;
final CoursesApi api;
CoursesRepositoryImpl(this.userDataSource, this.api);
@override
Future<List<Course>> getCourses() {
// 2️⃣
return api
.getCourses()
// 3️⃣
.then((courses) => courses.courses.map((e) => e.toEntity()).toList());
}
@override
Future<List<CourseProgress>> getCoursesProgresses() {
// 2️⃣
return userDataSource
.getCourseProgresses()
// 3️⃣
.then((progresses) => progresses.map((p) => p.toEntity()).toList());
}
@override
Future<void> updateCourseProgress(CourseProgress progress) {
// 2️⃣
return userDataSource
.updateCourseProgress(CourseProgressResponse.fromEntity(progress));
}
}And that’s pretty much all I wanted to show on the data layer!
🧑💻 If you want to explore the data layer further, have a look at the demo repository.
🧐 What’s next ?
We now have seen all the layers: presentation, domain and data. Phew 😮💨
There is however one topic left: how do all those layers work together, know about one another, etc. In the next and final chapter, we will see how to orchestrate our app.






