FlutterとRiverpod

## 概要
Flutter では、状態管理がアプリの設計やパフォーマンスに大きく影響します。その中でも **Riverpod** は、公式の `Provider` の進化版として登場し、**依存関係の管理やテストのしやすさ、パフォーマンスの向上** を実現しています。

**Riverpod**に関して学習し始めたばかりのため、忘れないよう簡単にまとめておこうと思います。

---

## Riverpod とは？
**Riverpod** は、`Provider` の開発者である **Remi Rousselet** によって作られた **状態管理ライブラリ** です。

### **Riverpod の特徴**
✅ **グローバルな状態管理が簡単** → `Provider` のスコープ管理を改善し、`BuildContext` なしで状態を管理できる。
✅ **依存関係（Dependency Injection）がシンプル** → `ref.read()` や `ref.watch()` を使って、状態を簡単に取得。
✅ **状態のスコープ管理ができる** → `ScopedProvider` や `AutoDispose` を活用して、メモリリークを防ぐ。
✅ **テストがしやすい** → `ProviderScope` を利用して状態をモックできる。


---

## **3. インストール**
### Riverpodのパッケージには3種類あります。

riverpod
https://pub.dev/packages/riverpod
flutter_riverpod
https://pub.dev/packages/flutter_riverpod
hooks_riverpod
https://pub.dev/packages/hooks_riverpod

筆者は`flutter_riverpod` パッケージを追加しています。

```sh
flutter pub add flutter_riverpod
```

また、`ProviderScope` を `main.dart` に設定する必要があります。

```dart
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';

void main() {
  runApp(const ProviderScope(child: MyApp()));
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      home: HomeScreen(),
    );
  }
}
```

✅ **`ProviderScope` をルートに配置することで、アプリ全体で Riverpod の状態を管理できる。**

---

## Riverpod の基本

### `StateProvider`（単純な状態管理）
変数のようなProviderでProviderのnotifierを参照して、直接値を変更します。
`StateProvider` を使うと、シンプルな状態（数値や文字列）を管理できます。

```dart
final counterProvider = StateProvider<int>((ref) => 0);

class CounterScreen extends ConsumerWidget {
  const CounterScreen({super.key});

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final counter = ref.watch(counterProvider);

    return Scaffold(
      appBar: AppBar(title: const Text("Counter")),
      body: Center(
        child: Text("Counter: $counter", style: const TextStyle(fontSize: 24)),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () => ref.read(counterProvider.notifier).state++,
        child: const Icon(Icons.add),
      ),
    );
  }
}
```
✅ **`ref.watch()` を使って状態を監視し、`ref.read()` で状態を更新。**

---

### `StateNotifierProvider`（複雑な状態管理）
より複雑な状態（リストやオブジェクトの管理）には、`StateNotifierProvider` を使います。
StateNotifierを継承したクラスを監視します。

```dart
import 'package:flutter_riverpod/flutter_riverpod.dart';

// StateNotifier を定義
class CounterNotifier extends StateNotifier<int> {
  CounterNotifier() : super(0);

  void increment() => state++;
}

final counterProvider = StateNotifierProvider<CounterNotifier, int>((ref) {
  return CounterNotifier();
});
```

✅ `StateNotifier` を使うことで、状態を明示的に管理できる。

---

### FutureProvider`（非同期処理の管理
`FutureProvider` を使うと、API 呼び出しなどの非同期データを管理できます。

```dart
final userProvider = FutureProvider<String>((ref) async {
  await Future.delayed(const Duration(seconds: 2));
  return "John Doe";
});

class UserScreen extends ConsumerWidget {
  const UserScreen({super.key});

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final userAsync = ref.watch(userProvider);

    return Scaffold(
      body: Center(
        child: userAsync.when(
          data: (data) => Text("User: $data"),
          loading: () => const CircularProgressIndicator(),
          error: (err, stack) => Text("Error: $err"),
        ),
      ),
    );
  }
}
```

✅ **`FutureProvider` を使うと、API の非同期データを簡単に扱える。**

---

## Providerとの比較

| 比較項目 | Riverpod | Provider |
|----------|---------|---------|
| `BuildContext` 必須 | ❌ 不要 | ✅ 必要 |
| グローバル管理 | ✅ 可能 | ✅ 可能 |
| 依存関係管理 | ✅ シンプル | ❌ 手動で管理が必要 |
| テストのしやすさ | ✅ 容易 | ❌ 難しい |

Riverpod の方が依存関係管理が簡単で、グローバルに状態を管理しやすそうですね。

---

## まとめ

✅ Riverpod は `Provider` の進化版で、より柔軟で使いやすい。
✅ 状態管理のスコープ管理が簡単で、依存関係の管理も直感的。
✅ グローバルな状態管理、非同期処理、テストのしやすさなど、多くのメリットがある。
✅ `StateProvider` / `StateNotifierProvider` / `FutureProvider` など、用途に応じたプロバイダを選べる。

---

## 参考リンク
https://flutter.salon/plugin/riverpod/

https://zenn.dev/jboy_blog/articles/9e16c80f18911c

https://riverpod.dev/