「グローバルスコープで定義した変数を任意のウィジェットに渡したり、値を変更したりしたい」
こんな時に便利なのが状態管理パッケージRiverpodの StateProvider ウィジェットです。
StateProviderを使用すれば外部から変更可能な変数を任意のウィジェットに渡すことができます。
それではStateProviderの基本的な使い方について解説していきます!
パッケージのインストール
まずはRiverpodのパッケージをFlutterプロジェクトにインストールします。
ターミナルで次のコマンドを実行してpubspec.yamlファイルにflutter_riverpodを追加します。
flutter pub add flutter_riverpod
次にflutter_riverpodを使用するdartファイルに次のコードをコピペします。
import 'package:flutter_riverpod/flutter_riverpod.dart';
StateProviderの基本的な使い方
StateProviderの基本的な使い方について解説します。
ProviderScopeの追加
ProviderScopeのchildプロパティの引数にルートとなるウィジェットを渡します。
こうすることでchildに渡したウィジェットの下位ウィジェットでStateProviderを使用できるようになります。
void main() => runApp(ProviderScope(child: MyApp()));
StateProviderの定義
StateProviderはグローバルスコープ(クラスや関数の外)で次のように定義します。
final 変数 = StateProvider((ref) => 戻り値);
final stateProvider = StateProvider((ref) => 0);
void main() => runApp(const ProviderScope(child: MyApp()));
ConsumerWidgetで使用環境を整える
StateProviderをStatelessWidgetで使用したい場合には、StatelessWidgetの代わりにConsumerWidgetを使用します。
ConsumerWidgetは基本的にStatelessWidgetと同じですが、buildメソッドの第二引数にWidgetRefクラスのオブジェクトref
を渡します。
以後このref
を使用してプロバイダの値を取得・変更できます。
class MyWidget extends ConsumerWidget {
const MyWidget({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
return ...;
}
}
StateProviderの値を取得
StateProviderの値を取得するにはref
のreadまたはwatchメソッドを使用します。
StateProviderで状態管理している値の変化を常に監視して反映させたい場合にはwatchメソッドが有効です。
final _counter = ref.watch(stateProvider);
class MyWidget extends ConsumerWidget {
const MyWidget({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
final _counter = ref.watch(stateProvider);
return Scaffold(
appBar: AppBar(title: const Text('Flutter')),
body: Center(
child: Text(
_counter.toString(),
style: TextStyle(fontSize: 70),
),
),
);
}
}
画像のサンプルコード
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
final stateProvider = StateProvider((ref) => 0);
void main() => runApp(const ProviderScope(child: MyApp()));
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return const MaterialApp(
home: MyWidget(),
);
}
}
class MyWidget extends ConsumerWidget {
const MyWidget({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
final _counter = ref.watch(stateProvider);
return Scaffold(
appBar: AppBar(title: const Text('Flutter')),
body: Center(
child: Text(
_counter.toString(),
style: TextStyle(fontSize: 70),
),
),
);
}
}
StateProviderの値を変更
StateProviderの値を変更するには次のようにupdateメソッドを使用します。
ref.read(stateProvider.notifier).update((変数) => 新しい値);
FloatingActionButton(
child: Icon(Icons.add),
onPressed: () {
ref.read(stateProvider.notifier).update((state) => state + 1);
},
),
サンプルコード
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
final stateProvider = StateProvider((ref) => 0);
void main() => runApp(const ProviderScope(child: MyApp()));
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return const MaterialApp(
home: MyWidget(),
);
}
}
class MyWidget extends ConsumerWidget {
const MyWidget({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
final _counter = ref.watch(stateProvider);
return Scaffold(
appBar: AppBar(title: const Text('Flutter')),
body: Center(
child: Text(
_counter.toString(),
style: TextStyle(fontSize: 70),
),
),
floatingActionButton: FloatingActionButton(
child: Icon(Icons.add),
onPressed: () {
ref.read(stateProvider.notifier).update((state) => state + 1);
},
),
);
}
}
まとめ
今回はRiverpodのStateProviderの基本的な使い方について解説しました。
StateProviderを使用すれば任意のウィジェットに外部から変更可能な変数を渡すことができるのでぜひ使ってみてください。