【Flutter】Fakeクラスでダミーデータを使ってフロントエンド開発を進める方法

この記事は約9分で読めます。

はじめに

Flutterでのアプリ開発では、バックエンドのAPIが完成する前にフロントエンドのUIを先に進めたい場合がよくある。この記事では、サーバー側のAPIが実装されていない間に、Flutterアプリでダミーデータを使って開発を進める方法を記載。

関連記事はこちら

JSONダミーデータをfakesクラスで用意

まず、Freezedアノテーションを使用してUserクラスを定義し、JSONからデータを生成するためのコードをFreezedで生成する。

このコードは、freezed パッケージによって生成されたコードを含む。そのため、flutter pub run build_runner build コマンドを実行して、関連するファイルを生成する必要がある。

Dart
import 'package:freezed_annotation/freezed_annotation.dart';

part 'user.freezed.dart';
part 'user.g.dart';

@freezed
class User with _$User {
  const factory User({
    required String id,
    required String name,
    required String email,
  }) = _User;

  factory User.fromJson(Map<String, dynamic> json) =>
      _$UserFromJson(json);
}

次に、実際のAPIレスポンスを模倣したJSONダミーデータをfakesクラスで用意。

Fakes クラスは、Flutterで使用されるダミーデータを生成するためのユーティリティクラス。

Fakeクラスに関する公式ドキュメントはこちら。

Fake class - test_api.fake library - Dart API
API docs for the Fake class from the test_api.fake library, for the Dart programming language.

fakes クラスを使用するためにインストールは必要ない。fakes クラスは、下記のようにプロジェクト内に自分で定義して、その中に静的なダミーデータリストを用意する。

Dart

import 'user.dart'; // Userクラスを定義したファイルをインポート

class Fakes {
  static final List<User> users = [
    {
      "id": "1",
      "name": "山田太郎",
      "email": "taro@example.com",
    },
    {
      "id": "2",
      "name": "佐藤花子",
      "email": "hanako@example.com",
    },
    // 他のダミーユーザーのデータを追加...
  ];
}

FakeUserRepositoryクラスの作成(APIリクエストの模倣)

ダミーデータを管理し、APIリクエストを模倣するメソッドfetchUsersを提供する。

将来的にはバックエンドからのデータ取得に置き換えるが、この時点では、Fakes.usersリストから即座にダミーデータを返している。

Dart
class FakeUserRepository {
  // User オブジェクトのリストを返す偽のAPI関数(fetchUsers())を作成
  Future<List<User>> fetchUsers() async {
    // Fakesクラスで作成したusersリストが返ってくる。
    return Future.value(Fakes.users);
  }
}

UIにデータ表示

Userオブジェクトを表示するウィジェットを作成する。HooksConsumerWidget を使用して、Riverpod のプロバイダーからデータを取得する。取得したUserリストをリストビューとして表示する。

  • usersProvider: ダミーデータのUserオブジェクトのリストを提供するRiverpodのプロバイダーです。Fakes.usersを直接返している。
  • UsersView: HookConsumerWidgetを継承したウィジェットで、usersProviderからデータを受け取り、UIに表示する。
  • Scaffoldウィジェット内でListView.builderを使用して、取得したUserオブジェクトのリストをリストビューとして表示。
Dart
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'your_project_path/models/user.dart'; // 実際のファイルパスに置き換えてください
import 'your_project_path/fakes/fakes.dart'; // Fakesクラスの実際のパスに置き換えてください

final usersProvider = Provider<List<User>>((ref) {
  return Fakes.users; // ダミーデータを提供
});

class UsersView extends HookConsumerWidget {
  const UsersView({Key? key}) : super(key: key); // コンストラクタにkeyを追加

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final users = ref.watch(usersProvider); // usersProviderからユーザーデータを取得

    return Scaffold(
      appBar: AppBar(
        title: const Text('ユーザー一覧'),
      ),
      body: users.isNotEmpty
          ? ListView.builder(
              itemCount: users.length,
              itemBuilder: (context, index) {
                final user = users[index];
                return ListTile(
                  title: Text(user.name),
                  subtitle: Text(user.email),
                  onTap: () {
                    // 詳細画面への遷移処理を追加(必要なら)
                  },
                );
              },
            )
          : const Center(child: Text('データがありません')), // データが空の場合は中央にテキストを表示
    );
  }
}

API実装されたら、リアルタイムのデータに切り替えて検証

サーバーのAPIが完成するまでの間、この方法でUIの開発を進めることができる。APIが実装されたら、リアルタイムのデータに切り替える。

例が、userデータではなく、drug_recordデータ

Dart
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:phr_app_expo/common/fakes/fakes.dart';
import 'package:phr_app_expo/data/clients/api_client.dart';
import 'package:phr_app_expo/data/clients/api_path.dart';
import 'package:phr_app_expo/data/clients/base_client.dart';
import 'package:phr_app_expo/data/entities/recoell/drug_record.dart';
import 'package:phr_app_expo/data/responses/drug_records_response.dart';

final drugRecordsRepositoryProvider = Provider<DrugRecordsRepository>((ref) {
  return DrugRecordsRepositoryImpl(ref.read(apiClientProvider));
  // 実際のリポジトリの代わりに、偽のリポジトリを使用する
  // return FakeDrugRecordsRepositoryImpl();
});

abstract class DrugRecordsRepository {
  Future<List<DrugRecord>> getDrugRecords();
}

class DrugRecordsRepositoryImpl extends DrugRecordsRepository {
  DrugRecordsRepositoryImpl(this._apiClient);
  final BaseClient _apiClient;

  @override
  Future<List<DrugRecord>> getDrugRecords() async {
    final response = await _apiClient.get(
      ApiPath.recoellDrugRecords,
    ) as Map<String, dynamic>;
    return DrugRecordsResponse.fromJson(response).drugRecords;
  }
}

class FakeDrugRecordsRepositoryImpl extends DrugRecordsRepository {
  FakeDrugRecordsRepositoryImpl();

  @override
  Future<List<DrugRecord>> getDrugRecords() async {
    return Fakes.drugRecords;
  }
}

APIリクエストとresponseの処理が無事できていれば、一発成功で表示されるはず!
無事表示された!

コメント

タイトルとURLをコピーしました