【flutter】hooks_riverpodとFreezedを使用してAPIからのJSONレスポンスをもとにFlutterアプリでユーザー情報を表示する
はじめに: Flutter、hooks_Riverpod、Freezedの概要
Hooks_Riverpod: flutter_hooks ライブラリと組み合わせて使用されるRiverpodのバージョン。FlutterのHook機能を活用し、より宣言的で簡潔なコードを書くことができる
Freezed: 不変の状態を持つデータクラスを生成することで、安全でメンテナンスしやすいコードを実現する。
ここでは、hooks_riverpodとFreezedを使用して、APIからのJSONレスポンスをもとにFlutterアプリでユーザー情報を表示する一連の流れをまとめる。
api_client.dart でAPIエンドポイント(**api_path.dart**で定義)からデータを取得し、そのJSONオブジェクトを UserResponse クラスを使用してDartオブジェクトに変換する。この変換は user_repository.dart で行われる。そして、変換されたユーザーデータをRiverpodプロバイダーを通じてUI層(user_view.dart)で表示する。
開発フローの例(ユーザー情報表示)
エンティティ/モデルの作成:
Freezedを使用して、ユーザー情報を格納するエンティティ(例: User)を定義。
build_runnerコマンドで、Freezedとjson_serializableを使ったコードを自動生成する
APIパスの定義:
api_path.dart にユーザー情報APIエンドポイント(例: /user/info)を追加。
APIクライアントの実装:
api_client.dart にユーザー情報取得メソッドを追加。
APIクライアントがAPIエンドポイントを利用してデータを取得
Responseクラスの実装:
APIレスポンスをパースするためのクラス(例: UserResponse)を responses ディレクトリに作成。
リポジトリの実装:
repositories にユーザー情報の取得と管理のビジネスロジックを実装。
リポジトリクラスがAPIクライアントを介してユーザー情報を取得し、そのデータを UserResponse オブジェクト(Dartオブジェクト)に変換する
Riverpodプロバイダーの設定:
ユーザー情報をUIに提供するためのRiverpodプロバイダーを設定。Riverpodプロバイダーがリポジトリのメソッドを使用して非同期にユーザー情報を取得し、UIに公開
UIの構築:
UIコンポーネントがRiverpodプロバイダーを使ってユーザー情報を表示
階層構造例
lib/
├── constants/
│ └── api_path.dart
├── models/
│ ├── user.dart
│ ├── user.freezed.dart
│ └── user.g.dart
├── services/
│ └── api_client.dart
├── repositories/
│ └── user_repository.dart
├── responses/
│ ├── user_response.dart
│ ├── user_response.freezed.dart
│ └── user_response.g.dart
├── providers/
│ └── user_provider.dart
└── views/
└── user_view.dart
開発順に見ていく
エンティティ/モデルの作成: Freezedを使用したデータモデルの定義
Freezedを使用して、不変性を持ちつつJSONデータを扱いやすいモデルを作成する。
// models/user.dart
import 'package:freezed_annotation/freezed_annotation.dart';
// 生成されるdartファイルを記述
part 'user.freezed.dart';
part 'user.g.dart';
// freezedでコード生成するために「@freezed」を記述
@freezed
class User with _$User { // withの後には「_$[class name]」の形式で記述
// プロパティを指定
const factory User({
required int id,
required String username,
required String email
}) = _User;
// サーバーから送られてくるJSONデータをDartのオブジェクトに変換する
factory User.fromJson(Map<String, dynamic> json) => _$UserFromJson(json);
}
続きは、こちらで記載しています。