メインコンテンツに進む
宣言型プログラミング

宣言型プログラミング

Stateless ウィジェットのようにビジネスロジックを記述できます。
ネットワークリクエストは必要に応じて自動的に再計算され、ロジックの再利用・合成・保守が容易になります。

共通のUIパターンを簡単に実装

共通のUIパターンを簡単に実装

Riverpodを使えば、入力しながら検索/引っ張って更新のような複雑なUIパターンでも、数行のコードで実装できます。

開発ツールに対応

開発ツールに対応

Riverpodはよくあるミスをコンパイルエラーとして扱い、コンパイラを強化します。カスタムlintルールやリファクタリングオプションも提供します。ドキュメント生成用のコマンドラインまで備えています。

特徴

  • 宣言型プログラミング
  • ネイティブネットワークリクエストに対応
  • ロード/エラーの自動ハンドリング
  • コンパイル時の安全性
  • 型安全なクエリパラメータ
  • テスト対応可
  • バニラDartで動作 (サーバー/CLI/...)
  • 組み合わせやすいステート
  • 引っ張って更新の動作に標準でサポート
  • カスタムlintルール
  • リファクタリング標準搭載
  • ホットリロードのサポート
  • ロギング
  • WebSocketサポート
  • ドキュメント生成

どこからでも共有ステートを宣言

main.dart と UI 側のコードの間を行き来する必要はありません。
共有ステートは、独立したパッケージや、利用するWidgetの近くなど、適切な場所に配置でき、テストのしやすさも維持されます。

// A shared state that can be accessed by multiple widgets at the same time.

class Count extends _$Count {

int build() => 0;

void increment() => state++;
}

// Consumes the shared state and rebuild when it changes
class Title extends ConsumerWidget {

Widget build(BuildContext context, WidgetRef ref) {
final count = ref.watch(countProvider);
return Text('$count');
}
}

ステートの再計算、UI の更新を最小限に

build メソッドの中でリストをソート / フィルタする必要はありません。高度なキャッシュ手法に頼る必要もありません。

Provider"families" を使って、本当に必要な時に限り、リストのソートや HTTP リクエストを実行できます。


List<Todo> filteredTodos(Ref ref) {
// Providers can consume other providers using the "ref" object.
// With ref.watch, providers will automatically update if the watched values changes.
final List<Todo> todos = ref.watch(todosProvider);
final Filter filter = ref.watch(filterProvider);

switch (filter) {
case Filter.all:
return todos;
case Filter.completed:
return todos.where((todo) => todo.completed).toList();
case Filter.uncompleted:
return todos.where((todo) => !todo.completed).toList();
}
}

リファクターで日々の作業を簡略化

Riverpod は、"Wrap widget in a Consumer"、のような、様々なリファクターを提供しています。リファクタリング一覧

リファクターで日々の作業を簡略化

lintルールでコードの保守性を保つ

Riverpodに特化した新しいlintルールは実装済みであり、今後さらに継続的に追加されます。これにより、コードが最適な状態に保たれます。lintルール一覧

lintルールでコードの保守性を保つ

プロバイダの安全な読み取り

プロバイダを読み取った結果、bad stateになることは決してありません。プロバイダを読み取るために必要なコードを書ければ、常に有効な値を取得できます。

これは非同期により値を取得する場合も同様に適用されます。Providerとは対照的に、Riverpodは読み込み/エラーケースのハンドリングを明確に処理できます。


Future<Configuration> configurations(Ref ref) async {
final uri = Uri.parse('configs.json');
final rawJson = await File.fromUri(uri).readAsString();

return Configuration.fromJson(json.decode(rawJson));
}

class Example extends ConsumerWidget {

Widget build(BuildContext context, WidgetRef ref) {
final configs = ref.watch(configurationsProvider);

// Use pattern matching to safely handle loading/error states
return switch (configs) {
AsyncData(:final value) => Text('data: ${value.host}'),
AsyncError(:final error) => Text('error: $error'),
_ => const CircularProgressIndicator(),
};
}
}

DevTools によるステートの検証

Riverpodを使うと、FlutterのDevToolsでステートが可視化されます。
加えて、より本格的なステート検証ツールの開発が進行中です。

DevTools によるステートの検証