ども、木村です。本業はデータサイエンティスト、副業でアプリ開発をしています。
本記事は、Riverpodの使い方と各種Providerを解説します。
これからRiverpodを使いたい方
今回のソースコードは以下で公開されています。
Riverpodとは?
RiverpodはFlutterにおける状態管理をサポートするパッケージです。
Riverpodが登場する前はProviderというパッケージで状態管理をすることが主流でした。
RiverpodはProviderと開発者が同じであり、Providerの上位互換/改良版と言えるような状態管理パッケージになります。
Providerの作者がRiverpodを作りました!
Riverpodを使うメリット
まず、RiverpodはProviderの弱みを補うような形で作られています。そのため、Riverpodでは以下のようなProviderの弱みを解消しています。
- ステートの参照許可のないwidgetからアクセスをすると
ProviderNotFoundException
のエラーが発生する - 同じ型のProviderを利用できない
など…
Riverpodは上記の問題を解消し、以下のようなメリット/特徴を持っています。
- ProviderNotFoundExceptionが起こらない!
- 同じ型で、複数の Providerを使える!
- Providerをグローバルに利用できる!
など
私自身、個人制作しているアプリでProviderからRiverpodにリプレイスを行いましたが、グローバルにProviderを定義できるのでソースコードが非常にスッキリしました。
Riverpodは従来のProviderパッケージの弱みを解消します!
Riverpodの基本的な使い方
まず、FlutterのデフォルトアプリであるカウンターアプリをRiverpodにリファクタリングしながら使い方を学んでいきたいと思います。
デフォルトアプリとの差分だけみたい方は以下を参考ください。
Riverpod のインストール
Riverpodのインストールを行います。Riverpodのパッケージは用途に合わせて3種類の中から選択します。
パッケージ名 | 用途 |
---|---|
flutter_riverpod | FlutterでRiverpodを使うための基本機能が提供される |
hooks_riverpod | flutter_hooksとRiverpodの両方を使用する想定で作られている |
riverpod | Dartパッケージ(Dartのみで動くため,Flutterに対応していない) |
今回はFlutterでかつ、Riverpodの最も基本的な部分を取り扱いますので「flutter_riverpod」を使用します。
インストールはpubspec.yamlに以下の記載を追記してください。
dependencies:
flutter:
sdk: flutter
flutter_riverpod: ^1.0.3 #追記
Providerの作成
providers.dartを新規で作成します。
ここには状態管理したい値を定義していきます。つまりProviderを実装します。
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter/material.dart';
final CounterProvider = ChangeNotifierProvider((ref) => Counter());
class Counter extends ChangeNotifier {
var _count = 0;
int get count => _count;
void increment() {
_count++;
notifyListeners();
}
}
重要なポイント
final CounterProvider = ChangeNotifierProvider((ref) => Counter());
上記がProviderで実装しています。
Riverpodには複数種類のProviderが用意されており、今回はその中の一つである「ChangeNotifierProvider」を使用します。
ChangeNotifierProviderでは、状態管理している値に変更があればその情報を参照しているwidgetに通知を飛ばし、UIを再描画してくれます。
ちなみに今回はCounter()クラスをProviderとして保存しています。
class Counter extends ChangeNotifier {}
Counter()クラスでは、ユーザーがボタンを押した回数を記録する_count変数と、ユーザーがボタンを押したときに_count変数に+1を行うincrement()メソッドを実装しています。
ChangeNotifierを継承し、increment()メソッドの中でnotifyListeners()を実行することで値の変更をUIに伝え、再描画をwidgetに促すことができます。
Providerの呼び出しと参照
main.dartを以下のように変更してください。
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:riverpod_demo/providers.dart';
void main() {
runApp(ProviderScope(child: const MyApp()));
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
var counterProvider = ref.watch(CounterProvider);
return Scaffold(
appBar: AppBar(
title: Text('Flutter Demo Home Page'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Text(
'You have pushed the button this many times:',
),
Text(
counterProvider.count.toString(),
style: Theme.of(context).textTheme.headline4,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
counterProvider.increment();
},
tooltip: 'Increment',
child: const Icon(Icons.add),
),
);
}
}
重要なポイント
runApp(ProviderScope(child: const MyApp()));
ProviderScope()で親widgetを囲うことで、それ以降の子widgetでProviderを呼び出すことができるようになります。
var counterProvider = ref.watch(CounterProvider);
ref.watch(<プロバイダー名>)を指定することで、providerを呼び出すことができます。
ちなみにこの.watch()が非常に優れもので、他のwidgetでCounterProviderの内容が変更されたらその変更を検知して、影響のある他のwidgetにも同様の変更を加え整合性を持つことができます。
ちなみに.watch()だけでなく、.read()を使うとProviderの変更はされず最初に呼び出したProviderの状態を使うことになります。
Text(
counterProvider.count.toString(),
style: Theme.of(context).textTheme.headline4,
),
counterProviderのcountにアクセスをしたい場合はcounterProvider.countのように記載すればアクセスが可能です。
またcounterProviderのincrement()メソッドにアクセスしたい時も同様にcounterProvider.increment()と記載すれば処理を実行できます。
まとめ:Riverpodを使って開発を効率的に!
Riverpodを使うことでコードの可読性や保守性が非常に良くなります。
私も初めて使った時あまりにもシンプルにコードを書けるようになったので感動しました。
Riverpodを使って一段階レベルの高いFlutterエンジニアに挑戦してみてはいかがでしょうか?
最新のFlutterの勉強方法 まとめ
Flutterを入門から実践レベルまで一通り学習できる方法をまとめました。