Open6

ref.watchの動作

mkikuchimkikuchi

refはWidgetRefで、abstractクラス。
watchの他に、listenとread, refreshが定義されている。

HookConsumerWidgetは、COnsumerWIdgetを継承している。
ConsumerWidget内の、_ConsumerState内で、refのgetterを持っている。
WidgetRef get ref => context as WidgetRef;

mkikuchimkikuchi

watchの実装は、COnsumerStatefulElement内にある。

  @override
  Res watch<Res>(ProviderListenable<Res> target) {
    return _dependencies.putIfAbsent(target, () {
      final oldDependency = _oldDependencies?.remove(target);

      if (oldDependency != null) {
        return oldDependency;
      }

      return _container.listen<Res>(
        target,
        (_, __) => markNeedsBuild(),
      );
    }).read() as Res;
  }
mkikuchimkikuchi

_dependenciesは、watchを呼んだProviderの値を管理している。
putIfAbsentは、targetをKeyにするValueがあればそれを返して、なければtargetをKeyにするProviderSubscriptionの値を返す。
_oldDependenciesからtargetを削除して、値があれば削除したoldDependencyを返す。
それ以外の場合は、targetをlistenして、変更があればmarkNeedsBuildを呼ぶ。
そして、取得したProviderのreadを呼んで値を返す。

mkikuchimkikuchi

つまり、ref.watchを最初に呼んだときは、_dependenciesにProviderListenableな値をKeyとして、ProviderSubscriptionする値を追加する。
ProviderSubscriptionの値は、targetのProviderListenableをlistenして、変更があればmarkNeedsBuildでリビルドさせる。
そして、その値をreadで返している。

二回目以降を呼んだときは、_dependenciesにtargetのvalueがあるので、その値をreadで呼ぶだけ。