非同期処理管理におけるRiverpodのFutureProviderとStreamProviderの活用事例
ここから記事本文
【注意】本記事はChatGPTによって生成されました
1. 導入:テーマの概要や重要性
Flutterアプリケーション開発において、非同期処理はAPI通信やデータベースアクセス、リアルタイムデータの取得など、多くの場面で欠かせない要素となっています。非同期処理を適切に管理しないと、UIが固まる・データ更新の反映漏れ・エラー処理の漏れなど、ユーザー体験に悪影響を及ぼす恐れがあります。そこで、状態管理パッケージであるRiverpodのFutureProvider
とStreamProvider
は、非同期処理を宣言的かつシンプルに扱う手助けをしてくれます。
FutureProvider
は単発の非同期処理(例:HTTPリクエストのレスポンス取得)に適し、StreamProvider
は連続的にデータが流れてくるケース(例:FirebaseのリアルタイムデータやWebSocket)に最適です。これらを活用することで、FlutterのUIは状態変化に応じて自動的に再構築され、非同期処理のロード中・成功・失敗の状態管理も非常に直感的に行えます。
本記事では、RiverpodのFutureProvider
とStreamProvider
の基礎から実践的な使い方、具体的なコード例、さらに応用的な活用シーンまでを詳しく解説します。Flutterの非同期処理管理の効率化や品質向上を目指す開発者にとって、有益な内容となるでしょう。
2. 背景・基礎知識
Riverpodとは?
RiverpodはFlutter向けの状態管理パッケージで、Remi Rousselet氏が開発しました。従来のStatefulWidget
とsetState
の組み合わせでは、状態が複雑化すると管理が困難になる問題を解決します。Riverpodはプロバイダーと呼ばれる抽象を使い、状態の宣言的管理と再利用性を高めています。
FutureProviderとStreamProviderの概要
Provider名 | 対象 | 返却型 | 用途例 |
---|---|---|---|
FutureProvider |
単発の非同期処理 | AsyncValue |
APIの1回限りのレスポンス取得 |
StreamProvider |
連続的な非同期データの取得 | AsyncValue |
Firebase、WebSocketの監視 |
どちらもAsyncValue
型の値を返し、loading
(読み込み中)、data
(成功)、error
(失敗)の状態を簡単に扱えます。
用語解説
- 非同期処理:処理の完了を待たずに次の処理を進めるプログラムの実行方法
- Future:将来のある時点で結果が返ってくる非同期処理の完了を表す型
- Stream:複数のデータを時間とともに逐次的に受け取るための非同期データの流れ
- AsyncValue:Riverpodが提供する、非同期処理の状態(loading/data/error)を包む型
3. 本論:技術的な詳細や仕組み、手順
FutureProviderの仕組み
FutureProvider
は、Futureを返す関数を登録し、Futureの状態変化をAsyncValue
で管理します。UIではref.watch()
で監視し、AsyncValue.when()
メソッドで状態に応じたWidgetを返す設計が基本です。
final userProvider = FutureProvider<User>((ref) async {
final response = await fetchUserFromAPI();
return response;
});
StreamProviderの仕組み
StreamProvider
は、Streamを返す関数を登録し、最新のデータをキャッシュしつつリアルタイムにUIを更新します。ref.watch()
で監視し、AsyncValue
で状態管理する点はFutureProvider
と同様です。
final chatMessagesProvider = StreamProvider<List<Message>>((ref) {
return chatRepository.getMessageStream();
});
アーキテクチャ上の位置づけ
- データ層:API呼び出しやDBアクセスの非同期処理を行う関数をプロバイダーに登録
-
状態層:
FutureProvider
・StreamProvider
が非同期処理の状態を管理 -
UI層:
ref.watch()
で非同期データの状態を監視し、状態に応じてWidgetを描画
4. 具体例・コード例
以下は、FutureProvider
でGitHubのユーザー情報を取得し、StreamProvider
でチャットメッセージをリアルタイムに表示するサンプルコードです。
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
// GitHubユーザー情報を取得するFutureProvider
final githubUserProvider = FutureProvider.family<Map<String, dynamic>, String>((ref, username) async {
final response = await Uri.parse('https://api.github.com/users/$username').readAsString();
return Map<String, dynamic>.from(jsonDecode(response));
});
// チャットメッセージのStreamProvider(ここでは疑似的なストリーム)
final chatMessagesProvider = StreamProvider<List<String>>((ref) {
return Stream.periodic(Duration(seconds: 2), (count) => List.generate(count + 1, (i) => 'メッセージ $i')).take(10);
});
void main() {
runApp(ProviderScope(child: MyApp()));
}
class MyApp extends StatelessWidget {
Widget build(BuildContext context) => MaterialApp(home: HomePage());
}
class HomePage extends ConsumerWidget {
Widget build(BuildContext context, WidgetRef ref) {
final githubUserAsync = ref.watch(githubUserProvider('flutter'));
final chatMessagesAsync = ref.watch(chatMessagesProvider);
return Scaffold(
appBar: AppBar(title: Text('Riverpod FutureProvider & StreamProvider')),
body: Column(
children: [
// FutureProviderの結果表示
githubUserAsync.when(
data: (user) => ListTile(
title: Text(user['login']),
subtitle: Text(user['bio'] ?? 'No bio'),
leading: CircleAvatar(
backgroundImage: NetworkImage(user['avatar_url']),
),
),
loading: () => CircularProgressIndicator(),
error: (e, _) => Text('Error: $e'),
),
Divider(),
// StreamProviderの結果表示
Expanded(
child: chatMessagesAsync.when(
data: (messages) => ListView.builder(
itemCount: messages.length,
itemBuilder: (_, i) => ListTile(title: Text(messages[i])),
),
loading: () => Center(child: CircularProgressIndicator()),
error: (e, _) => Center(child: Text('Error: $e')),
),
),
],
),
);
}
}
実行手順
- Flutterプロジェクトを作成(
flutter create riverpod_async_sample
) -
flutter_riverpod
をpubspec.yamlに追加 - 上記コードを
main.dart
にコピー -
flutter run
でアプリ起動
5. 応用・発展
複数の非同期Providerを組み合わせる
Riverpodは異なるProviderの値を組み合わせることが得意です。例えば、FutureProvider
の結果を受けて、条件に応じて別のStreamProvider
を切り替えることも可能です。
FirebaseやWebSocketとの連携
StreamProvider
はFirebase Firestoreのリアルタイムデータ監視や、WebSocketの受信データ管理にも理想的。リアルタイムチャットや通知機能の実装が容易になります。
エラーハンドリングのカスタマイズ
AsyncValue
のwhen
やmaybeWhen
を使い、UIにエラー内容をわかりやすく表示したり、リトライボタンを表示するなどUX向上も図れます。
6. まとめ・今後の展望
RiverpodのFutureProvider
とStreamProvider
は、Flutterの非同期処理管理を非常にシンプルかつ強力にします。非同期処理の状態(ロード・成功・失
Discussion