【ProviderとRiverpodの違い④】安全性の欠如
はじめに
前回に引き続き、今回もRiverpodのモチベーションについて解説していきます。
今回の記事では、「安全性の欠如」というセクションを掘り下げていきます。
Providerにおける安全性の欠如
公式ドキュメントの説明
Provider では、リファクタリングや大規模な変更中に
ProviderNotFoundException
が発生することが一般的です。実際、このランタイム例外は Riverpod が作られた主な理由の 1 つです。
Riverpod では、この例外は発生しません。
Providerにおける安全性の欠如とProviderNotFoundException
Providerでは、ウィジェットがその必要とするプロバイダーにアクセスできないときにProviderNotFoundException
が発生します。
これは、プロバイダーが適切にスコープされていないか、リファクタリング中にプロバイダーの配置が変更された場合によく発生します。
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return const MaterialApp(
home: Scaffold(
// ProviderはHomeScreenの外側に配置されていないため、HomeScreenでProviderを探すと例外が発生する
body: HomeScreen(),
),
);
}
}
class HomeScreen extends StatelessWidget {
const HomeScreen({super.key});
@override
Widget build(BuildContext context) {
// Provider.ofを使用してデータを取得しようとしていますが、Providerが存在しないため例外が発生する
final value = Provider.of<int>(context);
return Center(
child: Text('Value is $value'),
);
}
}
Riverpodにおける安全性の向上
Riverpodでは、プロバイダーの使用がコンパイル時にチェックされるため、ProviderNotFoundException
のような例外が発生することはありません。
Riverpodは、すべてのプロバイダーをグローバルにアクセス可能なものとして扱い、それぞれが一意の参照を持つため、ウィジェットの場所に依存することなく安全にアクセスすることができます。
以下の例では、ProviderScope
内で定義されたmyProvider
を使用しています。
myProvider
はアプリケーションのどの部分からでも安全にアクセスでき、ProviderNotFoundException
は発生しません。
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
final myProvider = Provider<int>((ref) => 10);
void main() {
runApp(
ProviderScope(
child: MaterialApp(
home: Scaffold(
body: Consumer(
builder: (context, ref, _) {
final value = ref.watch(myProvider);
return Text('Value is $value');
},
),
),
),
),
);
}
まとめ
RiverpodはProviderの安全性の問題を解決して、より安全で信頼性の高い状態管理を提供しています。
Providerの例外が開発中の問題となることを防ぎ、リファクタリングやプロジェクトのスケールアップが容易になります。
これにより、開発プロセスがスムーズになり、エラーのリスクが低減されるでしょう。
次回、「状態の破棄が難しい」デュエルスタンバイ!