0
0
Fluttermobile~20 mins

Repository pattern in Flutter - Mini App: Build & Ship

Choose your learning style9 modes available
Build: User List Screen
This screen shows a list of users fetched using a repository pattern. The repository handles data fetching and caching logic, separating data access from UI.
Target UI
-------------------------
| User List             |
|-----------------------|
| - Loading...          |
|                       |
|                       |
|                       |
|                       |
-------------------------
Create a UserRepository class that fetches user data from a fake API (simulate with Future.delayed).
UserRepository should have a method getUsers() returning a list of user names.
Create a UserListScreen widget that uses UserRepository to load and display users.
Show a loading indicator while fetching data.
Display the list of user names in a scrollable ListView.
Starter Code
Flutter
import 'package:flutter/material.dart';

// TODO: Create UserRepository class here

class UserListScreen extends StatefulWidget {
  @override
  State<UserListScreen> createState() => _UserListScreenState();
}

class _UserListScreenState extends State<UserListScreen> {
  // TODO: Declare variables for users and loading state

  @override
  void initState() {
    super.initState();
    // TODO: Load users from repository
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('User List')),
      body: Center(
        // TODO: Show loading or ListView of users
      ),
    );
  }
}
Task 1
Task 2
Task 3
Task 4
Task 5
Solution
Flutter
import 'package:flutter/material.dart';

class UserRepository {
  Future<List<String>> getUsers() async {
    await Future.delayed(Duration(seconds: 2));
    return ['Alice', 'Bob', 'Charlie', 'Diana'];
  }
}

class UserListScreen extends StatefulWidget {
  @override
  State<UserListScreen> createState() => _UserListScreenState();
}

class _UserListScreenState extends State<UserListScreen> {
  final UserRepository _userRepository = UserRepository();
  List<String> _users = [];
  bool _isLoading = true;

  @override
  void initState() {
    super.initState();
    _loadUsers();
  }

  void _loadUsers() async {
    final users = await _userRepository.getUsers();
    setState(() {
      _users = users;
      _isLoading = false;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('User List')),
      body: Center(
        child: _isLoading
            ? CircularProgressIndicator()
            : ListView.builder(
                itemCount: _users.length,
                itemBuilder: (context, index) {
                  return ListTile(
                    title: Text(_users[index]),
                  );
                },
              ),
      ),
    );
  }
}

We created a UserRepository class that simulates fetching user data with a 2-second delay. This class has a getUsers() method returning a list of user names.

In the UserListScreen widget, we use this repository to load users asynchronously in initState. While loading, a circular progress indicator shows. After loading, the user names display in a scrollable list.

This separation of data fetching logic into a repository helps keep UI code clean and makes it easier to change data sources later.

Final Result
Completed Screen
-------------------------
| User List             |
|-----------------------|
| • Alice               |
| • Bob                 |
| • Charlie             |
| • Diana               |
|                       |
|                       |
-------------------------
When the screen opens, a loading spinner shows for 2 seconds.
After loading, the list of user names appears.
User can scroll the list if it grows longer.
Stretch Goal
Add a Refresh button in the AppBar to reload the user list.
💡 Hint
Add an IconButton in AppBar actions that calls _loadUsers() when pressed.