🤐

Flutter showDialog()を閉じる際に、context.mounted が falseの場合の対応

2024/08/28に公開

概要(アラートが閉じれない)

showDialog()でアラートを表示し、

1, アラート内のボタンタップで、何かの処理して
2, そのあと、Navigator.of(context).pop() で閉じる

ような実装があり、

(※asyncな処理や、Providerの更新処理が追加された後に、)

Navigator.of(context).pop(); で閉じれない状況があった。

補足(context.mounted のチェック処理)

   TextButton(
      onPressed: () {
         // Navigator.pop(context);
         // NOTE: mounted のチェックを挟む 
         if (context.mounted) {
            Navigator.of(context).pop() 
         } else {
            // ここに入った場合、このタイミングでアラート閉じることができない!
         }
      },
      child: const Text('close'),
   );

のように、チェック処理をかますが、ここがfalseになると、そもそもアラートを閉じることができない。
とりあえず閉じたい、場合、下記の対応で可能。
(※そもそもの「asyncな処理やProviderの更新」などを見直すのがよいが)

Builder()を利用して、contextを生成する

閉じるボタンの親Widgetとして、Builder()で囲み、そのbuildContextを利用する。

Builder(
   builder: (builderNewContext) {
      return TextButton(
         onPressed: () {
            Navigator.pop(builderNewContext);
         },
         child: const Text('close'),
      );
   },),

こうすることで、現在のcontextにアクセスができ、アラートを閉じることができる。

追記

自分のコードベースのそもそもの実装方法に問題があった。
 
・showDialog()のWrapperするクラスの自作
・その際に、childWidgetを引数にとる実装(アラートの枠UIのみを共通化)
・showDialog(builder(newContext)) の、生成される新しいcontextが、
  -> 呼び出し元でアクセスできない状態だった。
  -> 引数でcontextを渡していてその古いcontextを、呼び出し元で使っていた状態

古いBuildContextを、閉じる際にも利用していたのが原因だった。

// イメージ
showDialog(builder:(newBuilderContext) { return AlertWidget() })
↑のnewBuilderContextをつかって、Navigator.pop()をすれば、問題なく閉じれた。

修正対応
showDialogを使ったアラートの自作ラッパークラスで、
・「childWidgetを引数」にせず、「Builder()を引数」に変更

こうすることで、呼び出し元でnewBuilderContext にアクセス可能となり、問題が解決。

Discussion