lelelemon’s blog

カメの歩みでのんびり学んでいます。

【Flutter】ConsumerWidget のビルドプロセス中にStateProviderの状態を更新しようとしてエラーにハマった

はじめに

Flutter で Riverpod を使って楽に状態変数を監視・更新できますが、画面ビルドプロセスで状態変数の初期状態を設定したい時にハマったときの対応メモです。

 

エラーについて

エラーが発生したコード
final CarouselController _controller = CarouselController();
// 現在選択中のカルーセルページ状態管理
final currentPageIndexProvider = StateProvider((ref) => 0);

// 現在選択中のラジオボタン状態管理
final selectedConditionProvider = StateProvider((ref) => '');

class InputRecordScreen1 extends ConsumerWidget {
  const InputRecordScreen1({
    super.key,
    required this.onSubmit,
  });

  final VoidCallback onSubmit;

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final l10n = L10n.of(context);

    final currentPageIndex = ref.watch(currentPageIndexProvider);

    final selectedCondition = ref.watch(selectedConditionProvider);

    if (selectedCondition.isEmpty) {
      ref.read(selectedConditionProvider.notifier).state =
          l10n.conditionOfTheKnotsSelection1;
    }

 

発生したエラー

StateNotifierListenerError (At least listener of the StateNotifier Instance of 'StateController<String>' threw an exception
when the notifier tried to update its state.

 

ビルドプロセス実行中の状態更新で発生していたので、ビルドプロセス完了後に実行する必要があった。

Future.microtask を使用してビルドプロセスの後に実行される非同期処理を登録します。

 

修正後のコード
    // 現在選択中のカルーセルページ状態管理
final currentPageIndexProvider = StateProvider((ref) => 0);

// 現在選択中のラジオボタン状態管理
final selectedConditionProvider = StateProvider((ref) => '');

class InputRecordScreen1 extends ConsumerWidget {
  const InputRecordScreen1({
    super.key,
    required this.onSubmit,
  });

  final VoidCallback onSubmit;

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final l10n = L10n.of(context);

    final currentPageIndex = ref.watch(currentPageIndexProvider);

    final selectedCondition = ref.watch(selectedConditionProvider);

    Future.microtask(() {
      if (selectedCondition.isEmpty) {
        ref.read(selectedConditionProvider.notifier).state =
            l10n.conditionOfTheKnotsSelection1;
      }
    });

終わりに

ビルドプロセス中の変数更新にエラーに遭遇することがよくあるので、そのようなときの一手として、今回のような非同期処理を使うことで対応できる場合があることがわかりました。

何かご参考になれば嬉しいです。