Skip to content
tezvyn:
Menu

Repository Pattern: Hide Your Data Sources

MediumHow cards are made

A repository is a contract that hides where your data lives. Your Flutter app should not care if a user profile comes from Firebase, SQLite, or a mock. Engineers often leak HTTP clients or database models into UI instead of returning domain models.

Why it exists

Flutter apps rarely pull from a single source. A typical project fetches JSON from a REST API, caches it in SQLite or Hive, and falls back to SharedPreferences for settings. Without a dedicated boundary, your widgets and state managers end up juggling network clients, serialization logic, and error handling. The repository pattern exists to seal that chaos behind a stable contract so the rest of your codebase can treat data access as a solved detail rather than an ongoing concern.

The mental model

Think of the repository as your app's personal librarian. The business logic walks up and asks for a specific book. The librarian knows which warehouse to check, whether to pull from the local shelf or order from a remote supplier, and how to handle a missing title. The requester never sees the supply chain, only the book. In code terms, that means your BLoC or Riverpod provider asks for a User object and has no idea if it came from Firestore, a local cache, or a hardcoded mock.

How it works

You start with an abstract Dart class that declares only the operations your domain needs, such as a method that asynchronously fetches a User by ID or streams a list of Orders. Behind that interface you build concrete implementations. One might wrap a Dio client for remote calls, another might wrap Drift or Hive for local storage. The repository implementation coordinates them. For example, it can return cached data immediately while triggering a background refresh, or it can merge remote and local streams. Because the rest of the app depends on the abstract class, you can swap the entire data layer during tests by injecting a fake that returns frozen values.

When to use it

Reach for this pattern when you have multiple data sources that need orchestration, when you want to unit-test business logic without hitting real networks, or when your team needs to keep UI code decoupled from third-party SDKs. It pays off the moment you have more than one origin for the same entity or when you anticipate switching providers, such as moving from a REST API to GraphQL or from Firebase to a self-hosted backend.

When not to use it

Avoid it for a throwaway prototype or a screen that performs a single unauthenticated GET request with no caching. The overhead of defining an interface, remote source, local source, and mapper for one endpoint creates boilerplate without buying clarity. If your data layer is trivial, let the state manager call the HTTP client directly and refactor later when the surface area grows.

One canonical example

Imagine a fitness app that tracks daily water intake. The HydrationRepository interface exposes methods to fetch today intake and log a new glass. The production implementation writes to a local Drift database for instant offline persistence and syncs to a remote Node API in the background. The UI layer and the Cubit that manages state only import HydrationRepository. During integration tests, you inject a fake repository that prepopulates known values, so your widget tests run in milliseconds without configuring a database or a mock server.

Interview question

Which scenario best justifies adding a repository layer according to the card?

  • a.A throwaway prototype that fetches from a hardcoded mock with no persistence layer.
  • b.A widget that checks whether data came from local cache or remote to decide how to render a sync badge.
  • c.An app that fetches from a REST API, caches in SQLite, and needs unit tests without real networks.Correct
  • d.A settings screen that performs a single unauthenticated GET with no caching needs.
Why?

The card recommends a repository when you must orchestrate multiple sources, cache offline, or test business logic without real networks. Distractor D violates the core idea that callers should not see the supply chain, while A and B describe trivial or throwaway cases where the pattern is unnecessary overhead.

Just read this? Test yourself on what you have been reading.

Put your scrolling time to good use

Learn one idea, try a quiz and save useful cards for revision. Tezvyn makes it easy to learn and stay current in your tech field, a few minutes at a time.

The iPhone app is on the way

We are building it. Until it lands, nothing here is held back from you: every interview card, your saved cards, streaks and the job board all work in Safari, plus hundreds of free practice quizzes of thirty questions each. Sign in and it all carries over to the app the day it arrives.

Want it as an icon? Tap Share at the bottom of Safari, then Add to Home Screen. It opens full screen and the cards you have read stay available offline.

Get it on Google PlayiPhone app coming soon

We are hiring for this. Open roles that interview on flutter — each one lists the topics its interview covers.

See open roles