Riverpod1.0.2のAn exception was thrown while buildingエラー対処法

`An exception was thrown while building`エラーが発生するパターンは複数あると思われますが、私が遭遇したパターンの原因と修正方法を記載します。

以下コードで実行エラーが発生しました。

```view_model.dart
final speedProvider = StateProvider<int>((ref) => 5);
final stepProvider = StateNotifierProvider<StepViewModel, double>(
    (ref) => StepViewModel(0, ref));

class StepViewModel extends StateNotifier<double> {
  final Ref _ref;
  StepViewModel(double state, this._ref) : super(state) {
    _ref.read(speedProvider.notifier).addListener((_) {
      _startTimer();
    });
  }
  void _startTimer() {
    final speed = _ref.read(speedProvider);
    ....
  }
}
```



```
======== Exception caught by widgets library =======================================================
The following ProviderException was thrown building Consumer(dirty, dependencies: [UncontrolledProviderScope], state: _ConsumerState#1fc32):
An exception was thrown while building StateProvider<int>#bd119.

Thrown exception:
Concurrent modification during iteration.

Stack trace:
#0      StateNotifier.addListener.<anonymous closure> (package:state_notifier/state_notifier.dart:276:9)
#1      StateNotifier.addListener (package:state_notifier/state_notifier.dart:279:6)
#2      StateProvider.create (package:riverpod/src/state_provider/base.dart:88:37)
#3      ProviderElementBase._buildState (package:riverpod/src/framework/provider_base.dart:481:26)
#4      ProviderElementBase.mount (package:riverpod/src/framework/provider_base.dart:382:5)
#5      _StateReader._create (package:riverpod/src/framework/container.dart:104:11)
#6      _StateReader.getElement (package:riverpod/src/framework/container.dart:92:52)
#7      ProviderContainer.readProviderElement (package:riverpod/src/framework/container.dart:510:19)
#8      ProviderContainer.read (package:riverpod/src/framework/container.dart:298:21)
#9      ProviderElementBase.read (package:riverpod/src/framework/provider_base.dart:661:23)
#10     StepViewModel._startTimer (package:my_app/view_model/step_view_model.dart:44:24)
#11     new StepViewModel.<anonymous closure> (package:my_app/view_model/step_view_model.dart:27:7)
#12     StateNotifier.addListener (package:state_notifier/state_notifier.dart:286:17)
#13     new StepViewModel (package:my_app/view_model/step_view_model.dart:24:39)
#14     stepProvider.<anonymous closure> (package:my_app/view_model/step_view_model.dart:8:14)
#15     _NotifierProvider.create (package:riverpod/src/state_notifier_provider/base.dart:98:29)
#16     ProviderElementBase._buildState (package:riverpod/src/framework/provider_base.dart:481:26)
#17     ProviderElementBase.mount (package:riverpod/src/framework/provider_base.dart:382:5)
#18     _StateReader._create (package:riverpod/src/framework/container.dart:104:11)
#19     _StateReader.getElement (package:riverpod/src/framework/container.dart:92:52)
#20     ProviderContainer.readProviderElement (package:riverpod/src/framework/container.dart:510:19)
#21     ProviderElementBase.watch (package:riverpod/src/framework/provider_base.dart:732:32)
#22     StateNotifierProvider.create (package:riverpod/src/state_notifier_provider/base.dart:54:26)
#23     ProviderElementBase._buildState (package:riverpod/src/framework/provider_base.dart:481:26)
#24     ProviderElementBase.mount (package:riverpod/src/framework/provider_base.dart:382:5)
```

# 原因

`addListener` メソッドのドキュメントに

> The [listener] callback will be called immediately on addition 

と書いてある通り、メソッドを読んだ時にコールバックが呼ばれます。
コールバックの中で同じProviderを参照したためエラーが起きました。


# 修正方法1

コールバック内でProviderを使わないようにすればOKです。

```
  StepViewModel(double state, this._ref) : super(state) {
    _ref.read(speedProvider.notifier).addListener((state) {
      _startTimer(state);
    });
  }
  void _startTimer(int state) {
    final speed = state;
    ...
  }
```

もしコールバック内でProviderを使いざるを得ない場合は、修正方法2が使えます。


# 修正方法2



>   synchronously whenever [state] changes.
>   Set [fireImmediately] to false if you want to skip the first,
>   immediate execution of the [listener].

ドキュメントにある通り、 `fireImmediately: false` を追加すれば `addListener`実行時にコールバックは呼ばれなくなります。
これならコールバック内でProviderを使ってもエラーが起きません。

```view_model.dart
    _ref.read(speedProvider.notifier).addListener((_) {
      _startTimer();
    }, fireImmediately: false);
```