Flutter: Navigatorで、Do not use BuildContexts across async gaps の警告が出る
結論:「if (!mounted) return;」の1文を追加する
2022/7/24 Flutter エラー・バグ日記
画面遷移をさせるため、ごく一般的な「Navigator.pushReplacement(context, ・・・」のような記述をしたところ、警告の波線が出るようになった。
カーソルを当てて内容を見ると、「Do not use BuildContexts across async gaps.」という警告コメントが表示される。
警告コメントの脇にある「Documentation」のリンクをたどると、以下の説明ページに飛んだ。
内容を読んだ自分なりの理解としては、非同期処理中に、「Navigator」のように、contextを渡す処理があると、非同期処理から戻ってきたときに、既に画面遷移が終わっていて、元の画面のcontextが無くなっているのでエラーになる、という状況を防ぎましょう、ということらしい。
上記「Documentation」にある対策は、「Navigator」の前に、「if (!mounted) return;」をつけるというもの。
確かに下記のように1文を追記すると、警告コメントは表示されなくなった。
class _MyWidgetState extends State<MyWidget> { ... // 非同期処理(async, await)の中でcontextを渡している void onButtonTapped() async { await Future.delayed(const Duration(seconds: 1)); // contextを渡す前に、contextが現在のWidgetツリー内に存在しているかどうかチェック // 存在しなければ、画面遷移済を意味するので、以降の画面遷移処理は行わない if (!mounted) return; Navigator.of(context).pop(); } }
要は、contextが無くなっていたら、早期リターンしてNavigatorを実行させないようにする、ということだと思われる。
※「mounted」プロパティについては以下に説明がある。Stateful Widgetのオブジェクトが、現在のWidgetツリー内に存在するか否かを示すbool型のプロパティのこと(存在しなければ、既に別のWidgetツリーに移っている=画面遷移している、ということだろう)。
確かに過去に作成していたアプリで、画面遷移をした後に、
This widget has been unmounted, so the State no longer has a context
というエラーが出たことがよくあった。
このとき、ググって対策を調べたら、「if (mounted) { }」で処理をラップすると良い、という情報があり、これでエラーを回避していた。
恐らく今回の警告は、この危険性を事前に察知してくれるものなのだろう。
「Documentation」によると、この警告は「Linter v1.1」となっている。
Flutter3にアップグレードして新規プロジェクトを作成すると、「pubspec.yaml」には「flutter_lints: ^2.0.0」がインポートされているので、恐らくアップグレードしたことでこの警告が機能するようになったのだと思われる(アップグレード前は「flutter_lints: ^1.0.0」だった)。
警告が出ると厄介に感じがちだが、こうして先回りしてエラーを防いでくれるのは、非常にありがたい。
\一般的なエラー対処法をまとめた記事はこちら/
リリースしたアプリ(全てFlutterで開発)
個人アプリ開発で役立ったもの
おすすめの学習教材
\超初心者向けでオススメな元Udemyの講座/
\キャンペーン時を狙えば安価で網羅的な内容が学べる(日本語訳あり)/
\Gitの基礎について無料で学べる/
おすすめの学習書籍
\実用的。image_pickerに関してかなり助けられた/
\Dartの基礎文法を素早くインプットできる/