Repository & Data Layer Quiz

ARCHITECTURE › Patterns

Which layer or class should other layers go through to reach the data layer?

Answer: The repository class, the entry point to the data layer

Repositories are the entry points to the data layer; other layers should never access data sources directly.

A repository needs to expose a continuously updating list of articles as the cache changes. What should it expose?

Answer: A Flow<List<Article>>

To notify consumers of data changes over time, the data layer exposes a Flow; suspend functions are for one-shot operations.

Why is a local database typically recommended as a repository's single source of truth?

Answer: It survives process death and keeps reads consistent offline

A persistent local source survives process death and supports offline-first, giving consistent data independent of the network.

Where should the logic that resolves conflicts between a network response and the cached database value live?

Answer: In the repository

Centralizing changes and resolving conflicts between multiple data sources is a core repository responsibility, keeping that policy out of the UI.

A data source must call a blocking network library. How should it stay main-safe?

Answer: Wrap the blocking call in withContext(ioDispatcher)

The data source is responsible for moving long-running blocking work off the calling thread, e.g. with withContext(ioDispatcher).

Which task is best run with WorkManager rather than a screen-scoped coroutine?

Answer: A business-critical sync that must survive process death

Business-oriented operations cannot be cancelled and must survive process death; WorkManager is the recommended tool for them.

Why does the data layer expose dedicated domain models instead of raw network DTOs?

Answer: To keep only needed fields, map external types, and avoid UI coupling

Separate models save memory, adapt external types to app types, and improve separation of concerns so the UI isn't coupled to the source format.

A repository method places a single order on the server and returns once, with no ongoing updates afterward. How should the data layer expose this one-shot operation?

Answer: As a suspend function that returns the created Order

One-shot CRUD operations are exposed as suspend functions; a Flow is only needed when consumers must be notified of changes over time.

Why should the objects a repository returns to higher layers be immutable?

Answer: So they can be shared across threads and never mutated into bad state

Immutable data can't be tampered with by other classes, avoiding inconsistent state, and can be shared across threads without synchronization.

A repository keeps a mutable in-memory cache that several coroutines read and write concurrently. How should it prevent corruption?

Answer: Guard every read and write with a Mutex inside withLock

A Mutex with withLock serializes concurrent coroutine access so the shared cache isn't corrupted; @Volatile only guarantees visibility, not atomic compound updates.

An analytics-event upload should still complete even if the user leaves the screen, but it does not need to survive process death. Where is it best run?

Answer: In an injected application-scoped CoroutineScope

This is an app-oriented operation that should live as long as the app process; an injected application-scoped scope fits, while WorkManager is reserved for business-critical work that must survive process death.

In an offline-first repository where Room is the single source of truth, how should fresh network data reach the UI?

Answer: Write the network response into Room and let the UI observe a Flow from Room

With a single source of truth, writes go to the database and consumers always observe the database Flow, so the UI reflects one consistent source after the network result is persisted.

How should a repository obtain the dispatcher it passes to withContext so that it remains easy to unit test?

Answer: Inject a CoroutineDispatcher through its constructor

Injecting the dispatcher lets tests substitute a test dispatcher, whereas hardcoding Dispatchers.IO couples the class to a real thread pool and makes deterministic testing hard.

According to modern Android data-layer guidance, how should repositories be organized in an app?

Answer: One repository for each different type of data the app handles

The guidance recommends a repository per type of data (e.g. MoviesRepository, PaymentsRepository), each potentially backed by several data sources, rather than a single god repository or per-screen repositories.

Back to Repository & Data Layer