業務にてFlutterでモバイル開発をしています。
最近ProviderをRiverpodに置き換える作業を行なったので共有します。
何が良いのか?
状態管理をアプリ全体で共有して使えることです。
Providerを使用していた頃はProviderを使用するWidgetの範囲を見定め、MultiProviderなどでラップしていました。
@override
Widget build(BuildContext context)
return provider.MultiProvider(
providers: [
provider.ChangeNotifierProvider(create: (ctx) => Counter()),
],
child:Scaffold()
しかしモーダル(showModalBottomSheet)を表示する際に、ある問題がおきます。
await showModalBottomSheet(
context: _context,
useRootNavigator: true, // コレ!!!
builder: (BuildContext context) {
final count = context.watch<Counter>.count
// 続く
ウィジェットツリーで親ではなくルート(MaretialAppなどその辺)をみてしまうんですね。
そうするとProviderが見つかりません、とエラーが吐かれます。
MultiProviderでラップする場所を変更せねば...という事態になります。
その点Riverpodではアプリの一番高いレイヤーで宣言し、グローバルで使用できるのでそんな問題は起きません。
void main() {
runApp(
// 本当に一番上
ProviderScope(
child: MyApp(),
),
);
}
そしてどこでも状態にアクセスすることができます。
provider.dart
final counterProvider = StateNotifierProvider<Counter, int>((ref) {
return Counter(ref);
});
home.dart
class HomeView extends ConsumerWidget {
const HomeView({Key? key}): super(key: key);
@override
Widget build(BuildContext context, WidgetRef ref) {
// どこでも呼べる!!!
final counter = ref.watch(counterProvider);
return Text('$counter');
}
}
ツリーのことを気にする必要がなくなりました。
Riverpodの良さはまだまだあるので、今後も共有していきます。