[Flutter]Riverpodの扱いが自由すぎるので制限をかけてみた

# この記事について
`provider`開発を主に行なっていたが`Riverpod`を使うことになりそうなので学習をしました。
ただグローバルでProvierを定義するため自由度が効きすぎて`set/get(購読)`がぱっと見で理解しにくかったため、そこの改善を試みた。

# 結論
先に結論からいいます。
- `Consumer`で再描画したいWidgetを指定する場合後述するコードは不向き
- `override`のアノテーション祭り

実際に開発で利用するかと言われたら多分使わないと思います。

# 本題
flutter hello wordであるカウンターアプリで作成

## 環境
```terminal
[✓] Flutter (Channel beta, 2.11.0-0.1.pre, on macOS 12.3.1 21E258 darwin-x64, locale ja-JP)
[✓] Android toolchain - develop for Android devices (Android SDK version 31.0.0)
[✓] Xcode - develop for iOS and macOS (Xcode 13.2.1)
[✓] Chrome - develop for the web
[✓] Android Studio (version 2020.3)
[✓] VS Code (version 1.66.2)
[✓] Connected device (2 available)
[✓] HTTP Host Availability
```

```yaml:pubspec.yaml
// 追加部分のみ
flutter_riverpod: ^1.0.3
```

## Provider
```dart
final countProvider = StateProvider<int>((ref) {
  return 0;
});
```

## ViewModel
```dart
abstract class HomeInput {
  late StateController<int> counterController;
}

abstract class HomeOutput {
  late String countString;
}

abstract class HomeViewModeType {
  late HomeInput inputs;
  late HomeOutput output;
}

class HomeViewModel implements HomeInput, HomeOutput, HomeViewModeType {
  HomeViewModel({Key? key, required this.ref}) {
    initialize();
  }

  final WidgetRef ref;

  @override
  late String countString;

  @override
  late StateController<int> counterController;

  @override
  late HomeInput inputs;

  @override
  late HomeOutput output;

  void initialize() {
    countString = ref.watch(countProvider).toString();
    counterController = ref.watch(countProvider.notifier);
    inputs = this;
    output = this;
  }
}

```
- input: notifierグループ
- output: stateグループ
- 直接`HomeViewModel`を触れなくするためにTypeを作成(後述)


## View
```dart
void main() {
  runApp(const ProviderScope(child: MyApp()));
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: Home(title: 'Flutter Demo Home Page'),
    );
  }
}

class Home extends ConsumerWidget {
  Home({Key? key, required this.title}) : super(key: key);
  String title = '';

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final HomeViewModeType homeViewModel = HomeViewModel(ref: ref);

    return Scaffold(
      appBar: AppBar(
        title: Text(title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            const Text(
              'You have pushed the button this many times:',
            ),
            Text(
              homeViewModel.output.countString,
              style: Theme.of(context).textTheme.headline4,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          homeViewModel.inputs.counterController.update((state) => state + 1);
        },
        tooltip: 'Increment',
        child: const Icon(Icons.add),
      ),
    );
  }
}

```

要点
`final HomeViewModeType homeViewModel = HomeViewModel(ref: ref);`

-> 型を`HomeViewModeType`にすることによって**input/outputを経由しないと**アクセスできなくしている。

> これを今回のタイトルである「制限」と考えてます


# まとめ
良かった点
- チーム全体でコードの統一性を確保できる
- 処理の流れの把握がイメージしやすい(個人的に)
- Riverpodの学習になった

悪かった点(重複)
- `Consumer`で再描画したいWidgetを指定する場合後述するコードは不向き
- `override`のアノテーション祭り

# 最後に
ここまで見ていただきありがとうございます！
Riverpodの学習を始めた日の投稿ですので、何か不手際がありましたらアドバイスお待ちしております。
なにかの役に立てれば幸いです！