Flutter showDialog()を閉じる際に、context.mounted が falseの場合の対応
概要(アラートが閉じれない)
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