The repository pattern helps organize how your app gets data. It keeps data fetching and storage separate from the UI, making your app easier to manage and test.
Repository pattern in Flutter
abstract class Repository { Future<String> fetchData(); } class ApiRepository implements Repository { @override Future<String> fetchData() async { // Simulate fetching data from API return 'Data from API'; } } class LocalRepository implements Repository { @override Future<String> fetchData() async { // Simulate fetching data from local storage return 'Data from Local Storage'; } }
The Repository is an abstract class or interface that defines data methods.
Concrete classes like ApiRepository and LocalRepository implement these methods to get data from different sources.
class ApiRepository implements Repository { @override Future<String> fetchData() async { return 'Data from API'; } }
class LocalRepository implements Repository { @override Future<String> fetchData() async { return 'Data from Local Storage'; } }
This Flutter app uses the repository pattern to get data. You can switch between ApiRepository and LocalRepository by changing one line. The UI shows the data fetched.
import 'package:flutter/material.dart'; abstract class Repository { Future<String> fetchData(); } class ApiRepository implements Repository { @override Future<String> fetchData() async { await Future.delayed(Duration(seconds: 1)); return 'Data from API'; } } class LocalRepository implements Repository { @override Future<String> fetchData() async { await Future.delayed(Duration(seconds: 1)); return 'Data from Local Storage'; } } void main() { runApp(MyApp()); } class MyApp extends StatefulWidget { @override State<MyApp> createState() => _MyAppState(); } class _MyAppState extends State<MyApp> { late Repository repository; String data = 'Loading...'; @override void initState() { super.initState(); // Change repository here to switch data source repository = ApiRepository(); loadData(); } void loadData() async { String result = await repository.fetchData(); setState(() { data = result; }); } @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( appBar: AppBar(title: Text('Repository Pattern Example')), body: Center(child: Text(data, style: TextStyle(fontSize: 24))), ), ); } }
Use the repository pattern to keep your UI code clean and focused only on showing data.
You can easily add more data sources by creating new repository classes.
Testing is easier because you can mock the repository without touching UI code.
The repository pattern separates data access from UI code.
It helps manage multiple data sources in one place.
It makes your app easier to test and maintain.