はじめに
hooks_riverpod
は、Flutterアプリの開発において、強力で柔軟な状態管理を提供します。特に、非同期処理を扱うためのStreamProvider
、状態を管理するためのNotifierProvider
やStateNotifierProvider
、および従来のChangeNotifier
に基づいたChangeNotifierProvider
は、それぞれの場面で最適なソリューションを提供します。
この記事では、StreamProvider、NotifierProvider、StateNotifierProvider、ChangeNotifierProviderの使い方について詳しく解説します。Flutter開発を効率化し、状態管理をよりシンプルにするための実践的な知識を提供します。
hooks_riverpodとは?
hooks_riverpod
は、Riverpod
の状態管理機能とFlutter Hooks
のフック機能を統合したライブラリです。Riverpodによる強力な状態管理に、Flutter Hooksを組み合わせることで、ウィジェットのライフサイクルに応じた簡潔な状態管理を実現します。
この記事では、特に以下のプロバイダについて詳しく見ていきます。
StreamProvider
:非同期データのストリームを管理。NotifierProvider
:Notifier
クラスをベースにした状態管理。StateNotifierProvider
:StateNotifier
を使って状態を管理する。ChangeNotifierProvider
:従来のChangeNotifier
ベースの状態管理。
※hooks_riverpod
が導入が済んでいない方は以下記事を確認してください。
StreamProviderの使い方
StreamProvider
は、非同期でデータのストリームを提供する際に使用します。たとえば、リアルタイムに更新されるデータや、ストリームAPIのデータを扱う場合に便利です。
例:StreamProviderでのリアルタイムカウント
final countStreamProvider = StreamProvider<int>((ref) {
return Stream.periodic(const Duration(seconds: 1), (count) => count);
});
class HomeScreen extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final asyncValue = ref.watch(countStreamProvider);
return Scaffold(
appBar: AppBar(title: const Text('StreamProvider Example')),
body: Center(
child: asyncValue.when(
data: (count) => Text('Count: $count'),
loading: () => CircularProgressIndicator(),
error: (err, stack) => Text('Error: $err'),
),
),
);
}
}
解説
StreamProvider
:非同期ストリームをプロバイダとして提供し、UIにリアルタイムで反映できます。Stream.periodic
:一定の間隔でデータを発行するストリームの生成方法です。asyncValue.when
:StreamProvider
の状態に応じて、データ・ローディング・エラーのそれぞれを表示します。
NotifierProviderの使い方
NotifierProvider
は、Notifier
クラスに基づいたプロバイダで、Notifier
を使って状態を管理し、それに応じてUIをリビルドする際に使用します。Notifier
は、状態を持たせ、notifyListeners
で更新するシンプルな仕組みです。
例:NotifierProviderでカウンターを管理
class CounterNotifier extends Notifier<int> {
@override
int build() => 0;
void increment() => state++;
}
final counterProvider = NotifierProvider<CounterNotifier, int>(() {
return CounterNotifier();
});
class HomeScreen extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final count = ref.watch(counterProvider);
return Scaffold(
appBar: AppBar(title: const Text('NotifierProvider Example')),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('Count: $count', style: const TextStyle(fontSize: 40)),
ElevatedButton(
onPressed: () => ref.read(counterProvider.notifier).increment(),
child: const Text('Increment'),
),
],
),
),
);
}
}
解説
Notifier
:シンプルな状態管理クラスで、状態を管理し、変更があった際にリビルドをトリガーします。NotifierProvider
:Notifier
をプロバイダとして使用し、状態を管理します。ref.watch(counterProvider)
:カウンターの現在の値を監視し、UIに反映します。ref.read(counterProvider.notifier).increment()
:Notifier
のメソッドを使って状態を変更します。
StateNotifierProviderの使い方
StateNotifierProvider
は、StateNotifier
クラスを使って、状態を細かく管理したいときに便利です。StateNotifier
は、状態を変更するためのメソッドを定義でき、状態の変更を安全に管理できます。
例:StateNotifierProviderでカウンターを管理
class CounterStateNotifier extends StateNotifier<int> {
CounterStateNotifier() : super(0);
void increment() => state++;
}
final counterStateNotifierProvider =
StateNotifierProvider<CounterStateNotifier, int>((ref) {
return CounterStateNotifier();
});
class HomeScreen extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final count = ref.watch(counterStateNotifierProvider);
return Scaffold(
appBar: AppBar(title: const Text('StateNotifierProvider Example')),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('Count: $count', style: const TextStyle(fontSize: 40)),
ElevatedButton(
onPressed: () =>
ref.read(counterStateNotifierProvider.notifier).increment(),
child: const Text('Increment'),
),
],
),
),
);
}
}
解説
StateNotifier
:状態を管理するためのクラスで、複雑なロジックにも対応できます。StateNotifierProvider
:StateNotifier
をプロバイダとして使用し、状態の管理を行います。state
:現在の状態を保持するプロパティで、状態が更新されるとリビルドがトリガーされます。
ChangeNotifierProviderの使い方
ChangeNotifierProvider
は、従来のChangeNotifier
ベースの状態管理を使いたい場合に有効です。ChangeNotifier
は、notifyListeners
メソッドを使って状態の更新を通知します。
例:ChangeNotifierProviderでカウンターを管理
class CounterChangeNotifier extends ChangeNotifier {
int _count = 0;
int get count => _count;
void increment() {
_count++;
notifyListeners();
}
}
final counterChangeNotifierProvider =
ChangeNotifierProvider<CounterChangeNotifier>((ref) {
return CounterChangeNotifier();
});
class HomeScreen extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final counter = ref.watch(counterChangeNotifierProvider);
return Scaffold(
appBar: AppBar(title: const Text('ChangeNotifierProvider Example')),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('Count: ${counter.count}',
style: const TextStyle(fontSize: 40)),
ElevatedButton(
onPressed: () => counter.increment(),
child: const Text('Increment'),
),
],
),
),
);
}
}
解説
ChangeNotifier
:リスナーに状態の変更を通知するためのクラスで、従来のFlutterの状態管理でよく使われます。ChangeNotifierProvider
:ChangeNotifier
をプロバイダとして使用し、notifyListeners
でUIをリビルドします。
まとめ
Flutterでの状態管理において、hooks_riverpod
は強力なツールです。今回紹介したStreamProvider
、NotifierProvider
、StateNotifierProvider
、およびChangeNotifierProvider
を適切に使い分けることで、アプリケーションの規模に関わらず、効率的に状態を管理できます。それぞれのプロバイダは特定のユースケースに最適化されており、状態の再利用や非同期データの管理に役立ちます。
コメント