Layer structure
Dependency flow
The dependency arrows point inward toward the domain:- Presentation depends on domain contracts (repositories, entities)
- Infrastructure implements those domain contracts
- Domain depends on nothing external
The domain layer contains no Flutter or HTTP imports — it is pure Dart. This makes it independently testable and portable.
Data flow for a movie list request
1
Provider triggers a load
A Riverpod
NotifierProvider calls loadNextPage(), incrementing the page counter and calling the repository method.2
Repository delegates to datasource
MovieRepositoryImpl forwards the call to the injected MoviesDatasource, applying no extra transformation in this case.3
Datasource fetches from the API
MoviedbDataSource makes an HTTP GET request via Dio to TheMovieDB API and deserializes the JSON response into MovieDbResponse.4
Mapper converts to domain entity
MovieMapper.movieDBToEntity() transforms each MovieMovieDB model into a Movie entity, constructing full image URLs in the process.5
State is updated
The new movies are appended to the existing list in the notifier’s state, triggering a widget rebuild.
Explore each layer
Domain layer
Entities, abstract datasource contracts, and repository interfaces that define the application’s business rules.
Infrastructure layer
Concrete HTTP datasource, API response models, mappers, and the repository implementation.
Presentation layer
Screens, widgets, and Riverpod providers that manage UI state and trigger data loads.