# 【ProviderとRiverpodの違い⑥】信頼性のあるパラメータ化機構の欠如

> Flutterにおける状態管理のためのProviderとRiverpodの違いについて、今回の記事では「信頼性のあるパラメータ化機構の欠如」を解決する方法について解説します。

- 公開日: 2024-10-22
- 更新日: 2024-10-24
- 著者: Matsu
- タグ: Flutter, Riverpod
- URL: https://tech.anycloud.co.jp/articles/provider-vs-riverpod-parameter

---

## はじめに

<div class="link-card-wrap"><a class="link-card" href="/articles/provider-vs-riverpod-discard-state/" target="_blank" rel="noopener noreferrer"><span class="link-card-body"><span class="link-card-title">【ProviderとRiverpodの違い⑤】状態の破棄が難しい</span><span class="link-card-description">Flutterにおける状態管理のためのProviderとRiverpodの違いについて、今回の記事では「状態の破棄が難しい」を解決する方法について解説します。</span><span class="link-card-meta"><img class="link-card-favicon" src="./linkcard-01-favicon.ico" alt=""><span class="link-card-domain">tech.anycloud.co.jp</span></span></span><img class="link-card-image" src="./linkcard-01-image.webp" alt=""></a></div>

前回に引き続き、今回もRiverpodのモチベーションについて解説していきます。

<div class="link-card-wrap"><a class="link-card" href="https://riverpod.dev/ja/docs/from_provider/motivation" target="_blank" rel="noopener noreferrer"><span class="link-card-body"><span class="link-card-title">モチベーション | Riverpod</span><span class="link-card-description">この記事は、なぜ Riverpod が存在するのかを詳しく説明することを目的としています。</span><span class="link-card-meta"><img class="link-card-favicon" src="./linkcard-02-favicon.svg" alt=""><span class="link-card-domain">riverpod.dev</span></span></span><img class="link-card-image" src="./linkcard-02-image.webp" alt=""></a></div>

今回の記事では、「[信頼性のあるパラメータ化機構の欠如](https://riverpod.dev/ja/docs/from_provider/motivation#%E4%BF%A1%E9%A0%BC%E6%80%A7%E3%81%AE%E3%81%82%E3%82%8B%E3%83%91%E3%83%A9%E3%83%A1%E3%83%BC%E3%82%BF%E5%8C%96%E6%A9%9F%E6%A7%8B%E3%81%AE%E6%AC%A0%E5%A6%82)」というセクションを掘り下げていきます。

## 信頼性のあるパラメータ化機構の欠如

### 公式ドキュメントの説明

> Riverpod では、.family 修飾子を使用して "外部のパラメータをもとに一意の" provider を宣言できます。
> 
> 実際、`.family` は Riverpod の最も強力な機能の 1 つであり、その革新の中心です。
> 
> これにより、ロジックの単純化が可能になります。
> 
> Provider で同様のことを実装しようとすると、使いやすさとタイプセーフの両方を犠牲にする必要があります。
> 
> さらに、Provider では同様の`.autoDispose`機構を実装できないため、`.family`の[同等](https://riverpod.dev/ja/docs/concepts/modifiers/family#prefer-using-autodispose-when-the-parameter-is-not-constant)の実装を妨げることになります。
> 
> 最後に、前述のように、ウィジェットは `InheritedWidget` をリッスンするのを決して止めません。
> 
> これにより、provider の状態が"動的にマウント"された場合、すなわちパラメータを使用して provider を構築する場合に、重大なメモリリークが発生します。
> 
> したがって、Provider に対する`.family` の同等の実装は現時点では根本的に不可能です。

### Providerにおけるパラメータ化されたプロバイダーの課題

Providerを使用してパラメータに基づくプロバイダーを実装するとき、一般的にはファクトリーパターンなどを使用して複数のインスタンスを管理することがあります。

また、状態の自動破棄（autoDispose）のような機能を実装するのは困難で、不要な状態がメモリに残り続けることがあります。

例えば、以下の例では、`UserProvider`を特定のユーザーIDに基づいて初期化していますが、異なるIDに基づいて複数の`UserProvider`インスタンスを容易に管理する方法は提供されていません。

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

class UserProvider with ChangeNotifier {
  final String userId;
  UserProvider(this.userId);

  // User data fetch logic
}

void main() {
  runApp(
    MultiProvider(
      providers: [
        ChangeNotifierProvider(create: (_) => UserProvider('user1')),
      ],
      child: MyApp(),
    ),
  );
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(home: Scaffold(body: Text('User Provider Example')));
  }
}
```

## Riverpodの.family修飾子による改善

Riverpodの`.family`修飾子を使用すると、パラメータに基づいてプロバイダーを動的に生成し、それぞれのインスタンスを自動的に管理することができます。

これにより、ロジックの単純化が可能になり、使いやすさとタイプセーフを保ちながらプロバイダーを柔軟に利用できます。

以下の例では、`userProvider`は`userId`をパラメータとして受け取り、それに基づいてユーザーデータを返します。

`.family`修飾子により、異なるユーザーIDに対する呼び出しは自動的に管理され、`.autoDispose`を使用することで、ウィジェットが不要になったときにプロバイダーの状態が自動的に破棄されます。

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

final userProvider = Provider.autoDispose.family<String, String>((ref, userId) {
  // Return user data based on userId
  return "Data for $userId";
});

void main() {
  runApp(
    ProviderScope(
      child: MaterialApp(home: Home()),
    ),
  );
}

class Home extends ConsumerWidget {
  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final userData = ref.watch(userProvider('user1'));
    return Scaffold(body: Text(userData));
  }
}
```

## まとめ

Riverpodの`.family`修飾子は、パラメータ化されたプロバイダーの管理を単純化し、Providerが直面する多くの問題を解決します。これにより開発者は、より少ないコードでより安全かつ効率的に状態管理ができるようになります。

次回、「副作用のトリガーが簡単でない」デュエルスタンバイ！

<div class="link-card-wrap"><a class="link-card" href="/articles/provider-vs-riverpod-side-effect/" target="_blank" rel="noopener noreferrer"><span class="link-card-body"><span class="link-card-title">【ProviderとRiverpodの違い⑦】副作用のトリガーが簡単でない</span><span class="link-card-description">Flutterにおける状態管理のためのProviderとRiverpodの違いについて、今回の記事では「副作用のトリガーが簡単でない」を解決する方法について解説します。</span><span class="link-card-meta"><img class="link-card-favicon" src="./linkcard-03-favicon.ico" alt=""><span class="link-card-domain">tech.anycloud.co.jp</span></span></span><img class="link-card-image" src="./linkcard-03-image.webp" alt=""></a></div>
