参考になる資料としては、有料ですが、
https://zenn.dev/riscait/books/flutter-riverpod-practical-introduction
こちらの本が、ほぼ全てが網羅されています。
Skimieでよく使われているのが、Provider と FutureProviderになります。
あと、NotifierProvider (StateNotifierProviderとも呼ばれる)は、一番多用されるものになるので、
最後に説明します。
(基本的には) 変更されない値(インスタンス)を持つことができます。
final firebaseAuthProvider = Provider((ref) => FirebaseAuth.instance);
上記のコードでは、FirebaseAuthクラスのインスタンスを持つProviderを作成しています。
riverpod_generatorでは、省略形で書くことができます。(このナレッジでは省略形は書きません。)
Providerは、単体で使うこともありますが、他のProviderと組み合わせることもできます。
final authenticatorProvider = Provider<Authenticator>((ref) {
return Authenticator(
auth: ref.watch(firebaseAuthProvider),
appleAuthenticator: ref.watch(appleAuthenticatorProvider),
googleAuthenticator: ref.watch(googleAuthenticatorProvider),
);
});
上記のコードのように、先ほどのFirebaseAuthのインスタンスのProviderを別のProviderの中で呼び出すことができます。
変更されない値を非同期的に処理することができるProviderです。
非同期処理を、Loading / error / data と処理の進行と結果に応じて返す値を変えてくれます。
APIを叩く時や時間がかかる処理の時に、使われるProviderです。
final resourceProvider = FutureProvider<Resources>((ref) async {
return ResourceService().find();
})
UIで使用するときには、
final state = ref.watch(eventPageNotifierProvider);
state.when(
// ローディング時
loading: () {
return const LoadingIndicator();
},
// エラー時
error: (error, __) {
Log.e(error.toString());
// リロードアイコン
return Container(
margin: const EdgeInsets.all(kSkimieMargin),
child: ReloadApiBtn(
onPressed: () =>
ref.read(eventPageNotifierProvider.notifier).refresh(),
),
);
},
// データ取得時
data: (state) {
final padding = MediaQuery.of(context).padding;
final activeTab = state.activeTabType;
List<Widget> children = [];
非同期の処理中の状態に応じてUIを変えることができる。
State(状態)と、それを操作するNotifierを持つProviderです。
非同期な初期化をする場合は、AsyncNotifierProviderを使用することもあります。
状態を定義します
import 'package:freezed_annotation/freezed_annotation.dart';
part 'state.freezed.dart';
@freezed
class HomePageState with _$HomePageState {
const factory HomePageState({
@Default(0) int num,
}) = _HomePageState;
}
Freezedを使います。Freezed + StateNotifier はセットで使います。
https://pub.dev/packages/freezed
この状態を持ったStateNotifierを継承したクラスを定義します。
class HomePageNotifier extends StateNotifier<HomePageState> {
HomePageNotifier() : super(const HomePageState());
void plus() async {
state = state.copyWith(num: state.num + 1);
}
void minus() async {
if ((state.num - 1) < 0) return;
state = state.copyWith(num: state.num - 1);
}
}
クラス内に、Stateを操作するメソッドを追加することができます。
このクラスをAutoDisposeStateNotifierProviderに持たせます。
final homePageNotifierProvider =
AutoDisposeStateNotifierProvider<HomePageNotifier, HomePageState>((ref) {
return HomePageNotifier();
});
NotifierProviderは、使い方によって、autodisposeのあるなしを決めた方がいいです。
あるUIのViewModelとして、使用する場合は、autodisposeをつけることで、参照されなくなったときに
自動でインスタンスを破棄してくれます。
autodisposeをつけない(一度参照されるとアプリを停止するまで、存在し続ける)例としては、
user情報を保持するものや、Skimieだとジェムやコインの状態を保持するProviderは、
アプリが動いている間は、いろいろなページで参照される可能性があるので、破棄しない方針の方が良いと思われます。
レポジトリーを参照:https://github.com/HI-0123/riverpod_explanation/tree/main