0
0
Fluttermobile~5 mins

Repository pattern in Flutter

Choose your learning style9 modes available
Introduction

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.

When your app needs to get data from different places like a web server and local storage.
When you want to change where data comes from without changing the UI code.
When you want to write tests for your data logic without involving the UI.
When your app grows and data handling becomes complex.
When you want to keep your code clean and easy to understand.
Syntax
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.

Examples
This class gets data from an API source.
Flutter
class ApiRepository implements Repository {
  @override
  Future<String> fetchData() async {
    return 'Data from API';
  }
}
This class gets data from local storage.
Flutter
class LocalRepository implements Repository {
  @override
  Future<String> fetchData() async {
    return 'Data from Local Storage';
  }
}
Sample App

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.

Flutter
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))),
      ),
    );
  }
}
OutputSuccess
Important Notes

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.

Summary

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.