👻
【Flutter】riverpod_generator 動作確認用コードサンプル
Riverpod の各プロバイダのサポート状況
「Riverpod の各プロバイダ」の 「riverpod_generator でのサポート状況」について、表にまとめます。更新履歴[1]
No. | プロバイダ | サポート状況 | 備考 |
---|---|---|---|
1 | Provider | サポート済 | |
2 | NotifierProvider | サポート済 | |
3 | AsyncNotifierProvider | サポート済 | |
4 | StateNotifierProvider | サポート予定無し(StateNotifier) | (Async)NotifierProvider で代替? |
5 | FutureProvider | サポート済 | |
6 | StreamProvider | サポート済 | 2023/03/01? v2.0.0 で対応済 |
7 | StateProvider | サポート予定無し(StateProvider) | [2] |
8 | ChangeNotifierProvider | サポート予定無し(ChangeNotifier) | (Async)NotifierProvider で代替? |
各プロバイダの動作確認用コードサンプル
Provider
Provider
test/riverpod_generator/provider_test.dart
import 'package:flutter_test/flutter_test.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
part 'provider_test.g.dart';
String Function(String s) hello(HelloRef ref) {
String hello(String s) {
return "Hello World $s";
}
return hello;
}
String Function(String s) helloF(HelloFRef ref, {required String init}) {
String hello(String s) {
return "$init $s";
}
return hello;
}
void main() {
group("basic", () {
test("Provider", () {
final container = ProviderContainer();
expect(helloProvider, isA<AutoDisposeProvider>());
final hello = container.read(helloProvider);
expect(hello("add"), "Hello World add");
});
});
group("family", () {
test("Provider", () {
final container = ProviderContainer();
expect(helloFProvider, isA<HelloFFamily>());
final hello = container.read(helloFProvider(init: "Hello World"));
expect(hello("add"), "Hello World add");
});
});
}
NotifierProvider
NotifierProvider
test/riverpod_generator/notifier_provider_test.dart
import 'package:flutter_test/flutter_test.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
part 'notifier_provider_test.g.dart';
class HelloNotifier extends _$HelloNotifier {
String build() {
return "Hello World";
}
void add(String s) {
state = "$state $s";
}
}
class HelloNotifierF extends _$HelloNotifierF {
String build({required String init}) {
return init;
}
void add(String s) {
state = "$state $s";
}
}
void main() {
group("basic", () {
test("NotifierProvider build", () {
final container = ProviderContainer();
expect(helloNotifierProvider, isA<AutoDisposeNotifierProvider>());
expect(container.read(helloNotifierProvider), "Hello World");
});
test("NotifierProvider add", () {
final container = ProviderContainer();
expect(helloNotifierProvider, isA<AutoDisposeNotifierProvider>());
expect(container.read(helloNotifierProvider), "Hello World");
container.read(helloNotifierProvider.notifier).add("add");
expect(container.read(helloNotifierProvider), "Hello World add");
});
});
group("family", () {
test("NotifierProvider build", () {
final container = ProviderContainer();
expect(helloNotifierFProvider, isA<HelloNotifierFFamily>());
expect(container.read(helloNotifierFProvider(init: "Hello World")),
"Hello World");
});
test("NotifierProvider add", () {
final container = ProviderContainer();
expect(helloNotifierFProvider, isA<HelloNotifierFFamily>());
expect(container.read(helloNotifierFProvider(init: "Hello World")),
"Hello World");
container
.read(helloNotifierFProvider(init: "Hello World").notifier)
.add("add");
expect(container.read(helloNotifierFProvider(init: "Hello World")),
"Hello World add");
});
});
}
AsyncNotifierProvider
AsyncNotifierProvider
test/riverpod_generator/async_notifier_provider_test.dart
import 'package:flutter_test/flutter_test.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
part 'async_notifier_provider_test.g.dart';
class HelloAsyncNotifier extends _$HelloAsyncNotifier {
Future<String> build() {
return Future.value("Hello AsyncNotifier");
}
void add(String s) async {
state = const AsyncLoading();
state = await AsyncValue.guard(() => Future.value("${state.value} $s"));
}
}
class HelloAsyncNotifierF extends _$HelloAsyncNotifierF {
Future<String> build({required String init}) {
return Future.value(init);
}
void add(String s) async {
state = const AsyncLoading();
state = await AsyncValue.guard(() => Future.value("${state.value} $s"));
}
}
void main() {
group("basic", () {
test("AsyncNotifierProvider build", () async {
final container = ProviderContainer();
expect(
helloAsyncNotifierProvider, isA<AutoDisposeAsyncNotifierProvider>());
expect(container.read(helloAsyncNotifierProvider), isA<AsyncLoading>());
// AsyncLoding から AsyncDataになるのを待つ
await Future<void>.value();
expect(
container.read(helloAsyncNotifierProvider), isA<AsyncData<String>>());
expect(container.read(helloAsyncNotifierProvider).value,
"Hello AsyncNotifier");
});
test("AsyncNotifierProvider add", () async {
final container = ProviderContainer();
expect(
helloAsyncNotifierProvider, isA<AutoDisposeAsyncNotifierProvider>());
expect(container.read(helloAsyncNotifierProvider), isA<AsyncLoading>());
await Future<void>.value();
expect(
container.read(helloAsyncNotifierProvider), isA<AsyncData<String>>());
expect(container.read(helloAsyncNotifierProvider).value,
"Hello AsyncNotifier");
container.read(helloAsyncNotifierProvider.notifier).add("add");
expect(container.read(helloAsyncNotifierProvider), isA<AsyncLoading>());
// AsyncLoding から AsyncDataになるのを待つ
await Future<void>.value();
expect(
container.read(helloAsyncNotifierProvider), isA<AsyncData<String>>());
expect(container.read(helloAsyncNotifierProvider).value,
"Hello AsyncNotifier add");
});
});
group("family", () {
test("AsyncNotifierProvider build", () async {
final container = ProviderContainer();
expect(helloAsyncNotifierFProvider, isA<HelloAsyncNotifierFFamily>());
expect(
container
.read(helloAsyncNotifierFProvider(init: "Hello AsyncNotifier")),
isA<AsyncLoading>());
// AsyncLoding から AsyncDataになるのを待つ
await Future<void>.value();
expect(
container
.read(helloAsyncNotifierFProvider(init: "Hello AsyncNotifier")),
isA<AsyncData<String>>());
expect(
container
.read(helloAsyncNotifierFProvider(init: "Hello AsyncNotifier"))
.value,
"Hello AsyncNotifier");
});
test("AsyncNotifierProvider add", () async {
final container = ProviderContainer();
expect(helloAsyncNotifierFProvider, isA<HelloAsyncNotifierFFamily>());
expect(
container
.read(helloAsyncNotifierFProvider(init: "Hello AsyncNotifier")),
isA<AsyncLoading>());
await Future<void>.value();
expect(
container
.read(helloAsyncNotifierFProvider(init: "Hello AsyncNotifier")),
isA<AsyncData<String>>());
expect(
container
.read(helloAsyncNotifierFProvider(init: "Hello AsyncNotifier"))
.value,
"Hello AsyncNotifier");
container
.read(
helloAsyncNotifierFProvider(init: "Hello AsyncNotifier").notifier)
.add("add");
expect(
container
.read(helloAsyncNotifierFProvider(init: "Hello AsyncNotifier")),
isA<AsyncLoading>());
// AsyncLoding から AsyncDataになるのを待つ
await Future<void>.value();
expect(
container
.read(helloAsyncNotifierFProvider(init: "Hello AsyncNotifier")),
isA<AsyncData<String>>());
expect(
container
.read(helloAsyncNotifierFProvider(init: "Hello AsyncNotifier"))
.value,
"Hello AsyncNotifier add");
});
});
}
FutureProvider
FutureProvider
test/riverpod_generator/future_provider_test.dart
import 'package:flutter_test/flutter_test.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
part 'future_provider_test.g.dart';
Future<String> helloFuture(HelloFutureRef ref) {
return Future.value("Hello Future");
}
Future<String> helloFutureF(HelloFutureFRef ref, {required String init}) {
return Future.value("Hello Future $init");
}
void main() {
group("basic", () {
test("FutureProvider", () async {
final container = ProviderContainer();
expect(helloFutureProvider, isA<AutoDisposeFutureProvider>());
expect(container.read(helloFutureProvider), isA<AsyncLoading>());
// AsyncLoding から AsyncDataになるのを待つ
await Future<void>.value();
expect(
container.read(helloFutureProvider),
isA<AsyncData<String>>().having((s) => s.value, "", "Hello Future"),
);
expect(container.read(helloFutureProvider).value, "Hello Future");
});
});
group("family", () {
test("FutureProvider", () async {
final container = ProviderContainer();
const init = "Initial";
expect(helloFutureFProvider, isA<HelloFutureFFamily>());
expect(container.read(helloFutureFProvider(init: init)),
isA<AsyncLoading>());
// AsyncLoding から AsyncDataになるのを待つ
await Future<void>.value();
expect(
container.read(helloFutureFProvider(init: init)),
isA<AsyncData<String>>()
.having((s) => s.value, "", "Hello Future $init"),
);
expect(container.read(helloFutureFProvider(init: init)).value,
"Hello Future $init");
});
});
}
StreamProvider
StreamProvider
test/riverpod_generator/stream_provider_test.dart
import 'package:flutter_test/flutter_test.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
part 'stream_provider_test.g.dart';
Stream<String> helloStream(HelloStreamRef ref) {
return Stream.value("Hello Stream");
}
Stream<String> helloStreamF(HelloStreamFRef ref, {required String init}) {
return Stream.value("Hello Stream $init");
}
void main() {
group("basic", () {
test("StreamProvider", () async {
final container = ProviderContainer();
expect(helloStreamProvider, isA<AutoDisposeStreamProvider>());
expect(container.read(helloStreamProvider), isA<AsyncLoading>());
// AsyncLoding から AsyncDataになるのを待つ
await Future<void>.value();
expect(
container.read(helloStreamProvider),
isA<AsyncData<String>>().having((s) => s.value, "", "Hello Stream"),
);
expect(container.read(helloStreamProvider).value, "Hello Stream");
});
});
group("family", () {
test("StreamProvider", () async {
final container = ProviderContainer();
const init = "Initial";
expect(helloStreamFProvider, isA<HelloStreamFFamily>());
expect(container.read(helloStreamFProvider(init: init)),
isA<AsyncLoading>());
// AsyncLoding から AsyncDataになるのを待つ
await Future<void>.value();
expect(
container.read(helloStreamFProvider(init: init)),
isA<AsyncData<String>>()
.having((s) => s.value, "", "Hello Stream $init"),
);
expect(container.read(helloStreamFProvider(init: init)).value,
"Hello Stream $init");
});
});
}
その他
非 AutoDispose 化
keepAlive
にtrue
を指定すると、非 AutoDispose になるようです。
- @riverpod
+ @Riverpod(keepAlive: true)
build.yaml
test/riverpod_generator/配下でコード生成するために設定しました。
build.yaml
targets:
$default:
sources:
include:
- $package$
- pubspec.yaml
- lib/**
- test/riverpod_generator/**
思ったことメモ
-
StateProvider は、これまで StateNotifierProvider で代替可能だったように、今後は、(Async)NotifierProvider でも代替可能だと思われます。一方で、StateProvider は、class 定義せずに気軽に使える点にメリットを感じているため、代替せずに利用継続していくのも良いのではと思いました。
-
プロバイダが自動生成されるため、例えば、「NotifierProvider の class 定義」と、その class 定義から「自動生成されるプロバイダのインスタンス」が、1:1 になるように思われる。
1:多、になるようにプロバイダのインスタンスを複数生成したい場合(この場合があるのか?)、どうやるか?
-
更新履歴
2023/01/21:初回投稿
2023/03/09:最新化 ↩︎ -
StateProvider は十分シンプルなため、ジェネレータで自動生成する必要が無いため、サポートしない?。https://github.com/rrousselGit/riverpod/discussions/1725 ↩︎
Discussion