はじめに
StateNotifierProvider
やChangeNotifierProvier
などのProvider
から、自作のProvier
を経由して、Widget
に値を伝播する方法のサンプルです。
メリット等は解説せず、導入後に「実際にどう書けばよいか分からない。。。」と詰まった方向けの内容となっています。
プロバイダから
ref
を取得する
この章単体で読んでもイメージが掴みにくかったのですが、サンプルコードと一緒だとイメージしやすいと思いサンプルを作りました。
詳細は公式リファレンスをご確認ください。
環境
Flutter: 3.0.5
hooks_riverpod: 1.0.4
flutter_hooks: 0.18.5
結論
import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
class SamplePage extends HookConsumerWidget {
const SamplePage({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
return Scaffold(
body: Center(
child: Text(ref.watch(calculatorProvider).calculatedValue.toString()),
),
floatingActionButton: FloatingActionButton(
onPressed: ref.read(numberNotifierProvider.notifier).plusOne,
child: const Icon(Icons.add),
),
);
}
}
final calculatorProvider = Provider((ref) => Calculator(ref));
class Calculator {
Calculator(this.ref);
final Ref ref;
int get calculatedValue {
return ref.watch(numberNotifierProvider) * 2;
}
}
final numberNotifierProvider =
StateNotifierProvider<NumberNotifier, int>((ref) => NumberNotifier());
class NumberNotifier extends StateNotifier<int> {
NumberNotifier() : super(0);
void plusOne() {
state++;
}
}
おまけ①
上記書き方をベースに、Calculator
の部分をViewModelにすることで、MVVMライクなViewModelのProviderを作ることもできます。
※FlutterでMVVMアーキテクチャを推奨している意味合いではございません。本記事ではアーキテクチャについては取り扱いません。
import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
class SettingPage extends HookConsumerWidget {
const SettingPage({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
return Scaffold(
body: Center(
child: Text(
ref.watch(settingPageViewModelProvider).darkMode
? 'ダークモード'
: 'ライトモード',
),
),
);
}
}
final settingPageViewModelProvider =
Provider((ref) => SettingPageViewModel(ref));
class SettingPageViewModel {
SettingPageViewModel(this.ref);
final Ref ref;
bool get darkMode {
return ref.watch(darkModeNotifierProvider);
}
}
final darkModeNotifierProvider =
StateNotifierProvider<DarkModeNotifier, bool>((ref) => DarkModeNotifier());
class DarkModeNotifier extends StateNotifier<bool> {
DarkModeNotifier() : super(false);
void change() {
state = !state;
}
}
おまけ②
また、Caluculator
を以下のように書いても上記はじめのコードと全く同じくProvider
に値を伝播させることができます。
final calculatorProvider =
Provider((ref) => Calculator(ref.watch(numberNotifierProvider)));
class Calculator {
Calculator(this.value);
final int value;
int get calculatedValue {
return value * 2;
}
}
おわりに
実装に悩んでいる際StateNotifier
やChangeNotifier
を使用して、Widget
に情報を伝える方法を解説している記事は多くヒットしたのですが、Provider
を経由した場合の記事がほとんどヒットしなかったので、サンプルコードを記事にしてみました。
この記事で挫折する人を減らしてRiverpodの楽しさを共有できたら幸いです。
// おまけの方が行数多い。。。