【Flutter】バージョンアップしたらLinterが警告を出したので解消してみた

2023/01/27に公開

バージョンアップしたらLinterが警告を出した

前回、FlutterをバージョンアップしたらWarningが出たので解消しました。

https://zenn.dev/arafipro/articles/2023-01-26-flutter-version-update-warning

ところが解消したことに満足してLinterが警告を出していたことに気がつきませんでした。
よく見るとわかりますが、問題のところに①のマークが・・・。
Visual Studio Codeのターミナルでいろいろやっていたのに、集中すると気づかないものですね。

Warningの内容を確認

さて、本題に戻りますが問題の内容は以下の通り

Don't use 'BuildContext's across async gaps.
Try rewriting the code to not reference the 'BuildContext'.

ちなみにVisual Studio Codeでは以下のような感じで表示されます。

警告文の中にリンク先が以下のページです。

https://dart-lang.github.io/linter/lints/use_build_context_synchronously.html

警告文をDeepLで翻訳

まずは警告文をDeepLで翻訳してみる。

'BuildContext'を非同期なギャップにまたがって使用しない。
'BuildContext'を参照しないようにコードを書き換えてみてください。

そして警告文を踏まえてコードを確認。

async {
  final navigator = Navigator.push(
    context,
    MaterialPageRoute(
      builder: (context) => const ListPage(),
    ),
  );
  await model.addMemo();
  await showDialog(
    context: context,
    builder: (
      BuildContext context,
    ) =>
        const CustomAlertDialog(
      title: '保存しました',
      buttonText: 'OK',
    ),
  );
  await navigator;
}

なるほど、await model.addMemo()await navigatorの間にawait showDialog()が挟まっているのが問題なんだな。

いろいろ試してみる

まずは単純に順番を変えてみる。
await model.addMemo()await showDialog()の直上に移動。

async {
  final navigator = Navigator.push(
    context,
    MaterialPageRoute(
      builder: (context) => const ListPage(),
    ),
  );
  await showDialog(
    context: context,
    builder: (
      BuildContext context,
    ) =>
        const CustomAlertDialog(
      title: '保存しました',
      buttonText: 'OK',
    ),
  );
  await model.addMemo(); // ここに移動
  await navigator;
}

そうすると警告は消えました。
しかし、動作確認すると思った挙動にならなくて却下。

次は警告文のリンク先を見てみる。
if (!context.mounted) return;を付け加えると解決しそう。
ただどこにいれていいのかわからず適当に入れてみるもまったく解決せず。
if (!context.mounted) return;の位置によってはこれ自体が警告対象に・・・。
埒がつかないのでいったん却下。

次は検索キーワードを以下のようにして検索する。

use_build_context_synchronously showDialog

検索結果の2ページ目にこちらの記事を発見。
参考にさせていただき、ありがとうございます!!
https://qiita.com/Kurogoma4D/items/4700f08406e9a70e104c
記事を読むとawait showDialog()を引数に渡して、引数から非同期動作させる方法を発見。
早速、試してみる。
以下のようにawait showDialog()を引数dialogResultに渡して、引数dialogResultを下に移動したら見事に解消。

async {
  final navigator = Navigator.push(
    context,
    MaterialPageRoute(
      builder: (context) => const ListPage(),
    ),
  );
  final dialogResult = showDialog( // 引数dialogResultに渡す
    context: context,
    builder: (
      BuildContext context,
    ) =>
        const CustomAlertDialog(
      title: '保存しました',
      buttonText: 'OK',
    ),
  );
  await model.addMemo();
  await dialogResult; // 引数dialogResultを移動
  await navigator;
}

これだと動作の順番は変わらないので動作確認もバッチリでした。

実はヒントがすぐそこにあった

ここまで警告文を解消してきました。
ただお気づきの方もいられるかもしれませんが、ヒントがコードの中に隠されていました。
実はNavigator.push()も同じように引数navigatorに渡しているんです。

async {
  final navigator = Navigator.push( // 引数navigatorに渡す
    context,
    MaterialPageRoute(
      builder: (context) => const ListPage(),
    ),
  );
  final dialogResult = showDialog(
    context: context,
    builder: (
      BuildContext context,
    ) =>
        const CustomAlertDialog(
      title: '保存しました',
      buttonText: 'OK',
    ),
  );
  await model.addMemo();
  await dialogResult;
  await navigator; // 引数navigatorを移動
}

今回も同じやり方でよかったんですね。
こんなことに気づかないなんて・・・。
年取って頭が硬くなったなぁ〜と改めて実感したのでした。

「日本株ひとこと投資メモ」をリリースしています

Flutter学習のアウトプットの一環として「日本株ひとこと投資メモ」を公開しました。
簡単に使えるライトな投資メモアプリです。
みなさんの投資ライフに少しでも活用していただきれば幸いです。

🔻🔻🔻iPhone版はこちら🔻🔻🔻
https://apps.apple.com/jp/app/日本株ひとこと投資メモ/id1665808160

🔻🔻🔻Android版はこちら🔻🔻🔻
https://play.google.com/store/apps/details?id=com.arafipro.jpstockminimemo

GitHubで編集を提案

Discussion