# Architecture Learning Journey
In this learning journey you will learn about the Now in Android app architecture: its layers, key classes and the interactions between them.
## Goals and requirements
The goals for the app architecture are:
* Follow the [official architecture guidance](https://developer.android.com/jetpack/guide) as closely as possible.
* Easy for developers to understand, nothing too experimental.
* Support multiple developers working on the same codebase.
* Facilitate local and instrumented tests, both on the developer’s machine and using Continuous Integration (CI).
* Minimize build times.
## Architecture overview
The app architecture has three layers: a [data layer](https://developer.android.com/jetpack/guide/data-layer), a [domain layer](https://developer.android.com/jetpack/guide/domain-layer) and a [UI layer](https://developer.android.com/jetpack/guide/ui-layer).
Step
|
Description
|
Code
|
1
|
On app startup, a WorkManager job to sync all repositories is enqueued.
|
SyncInitializer.create
|
2
|
The ForYouViewModel calls GetSaveableNewsResourcesUseCase to obtain a stream of news resources with their bookmarked/saved state. No items will be emitted into this stream until both the user and news repositories emit an item. While waiting, the feed state is set to Loading .
|
Search for usages of NewsFeedUiState.Loading
|
3
|
The user data repository obtains a stream of UserData objects from a local data source backed by Proto DataStore.
|
NiaPreferencesDataSource.userData
|
4
|
WorkManager executes the sync job which calls OfflineFirstNewsRepository to start synchronizing data with the remote data source.
|
SyncWorker.doWork
|
5
|
OfflineFirstNewsRepository calls RetrofitNiaNetwork to execute the actual API request using Retrofit.
|
OfflineFirstNewsRepository.syncWith
|
6
|
RetrofitNiaNetwork calls the REST API on the remote server.
|
RetrofitNiaNetwork.getNewsResources
|
7
|
RetrofitNiaNetwork receives the network response from the remote server.
|
RetrofitNiaNetwork.getNewsResources
|
8
|
OfflineFirstNewsRepository syncs the remote data with NewsResourceDao by inserting, updating or deleting data in a local Room database.
|
OfflineFirstNewsRepository.syncWith
|
9
|
When data changes in NewsResourceDao it is emitted into the news resources data stream (which is a Flow).
|
NewsResourceDao.getNewsResources
|
10
|
OfflineFirstNewsRepository acts as an intermediate operator on this stream, transforming the incoming PopulatedNewsResource (a database model, internal to the data layer) to the public NewsResource model which is consumed by other layers.
|
OfflineFirstNewsRepository.getNewsResources
|
11
|
GetSaveableNewsResourcesUseCase combines the list of news resources with the user data to emit a list of SaveableNewsResource s.
|
GetSaveableNewsResourcesUseCase.invoke
|
12
|
When ForYouViewModel receives the saveable news resources it updates the feed state to Success .
ForYouScreen then uses the saveable news resources in the state to render the screen.
|
Search for instances of NewsFeedUiState.Success
|
## Data layer
The data layer is implemented as an offline-first source of app data and business logic. It is the source of truth for all data in the app.
![Diagram showing the data layer architecture](images/architecture-3-data-layer.png "Diagram showing the data layer architecture")
Each repository has its own models. For example, the `TopicsRepository` has a `Topic` model and the `NewsRepository` has a `NewsResource` model.
Repositories are the public API for other layers, they provide the _only_ way to access the app data. The repositories typically offer one or more methods for reading and writing data.
### Reading data
Data is exposed as data streams. This means each client of the repository must be prepared to react to data changes. Data is not exposed as a snapshot (e.g. `getModel`) because there's no guarantee that it will still be valid by the time it is used.
Reads are performed from local storage as the source of truth, therefore errors are not expected when reading from `Repository` instances. However, errors may occur when trying to reconcile data in local storage with remote sources. For more on error reconciliation, check the data synchronization section below.
_Example: Read a list of topics_
A list of Topics can be obtained by subscribing to `TopicsRepository::getTopics` flow which emits `List