【Flutter】警告を出したので解消してみた

2023/06/08に公開

同じ警告だけど、今回は・・・・

以前、「FlutterをバージョンアップしたらLinterが警告を出したので解消してみた」を投稿しました。

https://zenn.dev/arafipro/articles/2023-01-27-flutter-linter-warning

今回もまた同じ警告が出たので、自身の記事を参考に解決を試みました。
まずは記事通りにやってみました。
警告は解消されるのですが、どうやっても自分の思った挙動で動きません。
再び、調べることになりました。
今回はChatGPTが活躍しますよ。

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'を参照しないようにコードを書き換えてみてください。

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

onPressed: () async {
  final searchItem = await gojyuonItem(0);
  await Navigator.push(
    context,
    MaterialPageRoute(
      builder: (context) =>
          OrderPage(searchData: searchItem),
    ),
  );
},

今回の場合はfinal searchItem = await gojyuonItem(0);await Navigator.pushの前にあることが問題になります。
そこで、順番を入れ替えるんですが・・・

しかし、警告どころかエラーが出てしまいます。
もう一度、コードを確認します。

onPressed: () async {
  // 変数searchItemで受け取る
  final searchItem = await gojyuonItem(0);
  await Navigator.push(
    context,
    MaterialPageRoute(
      builder: (context) =>
          // 変数searchItemをOrderPageの引数として渡す
          OrderPage(searchData: searchItem),
    ),
  );
},

それもそのはずで、await gojyuonItem(0)から受け取った結果を変数searchItemで受けます。
そしてawait Navigator.push内のOrderPage(searchData: searchItem)の引数に渡します。
そうです、入れ替えるとプログラム自体が動かなくなるのです。

ちなみに、await Navigator.pushの前に// ignore: use_build_context_synchronouslyを挿入することで警告を一時的に消すことはできます。
しかし、警告が出るということは、何か弊害が起きる可能性があるはずです。
それだけは避けたいので、違う方法を考えます。

ChatGPTに聞いてみた

ChatGPTに質問するプロンプトを思いつきました。
そこで、久しぶりにChatGPTに聞いてみることしました。
ChatGPTに質問した内容は下記の通りです。

コードA
SquareButton(
  text: "あ",
  onPressed: () async {
    final searchItem = await gojyuonItem(0);
    // ignore: use_build_context_synchronously
    await Navigator.push(
      context,
      MaterialPageRoute(
        builder: (context) =>
            OrderPage(searchData: searchItem),
      ),
    );
  },
),

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

コードB
final navigator = Navigator.push(
  context,
  MaterialPageRoute(
    builder: !settingsModel.startDisplayPage
        ? (context) => const ListPage()
        : (context) => const GridPage(),
  ),
);
final dialogResult = showDialog(
  context: context,
  builder: (
    BuildContext context,
  ) =>
      CustomAlertDialog(
    title: AppLocalizations.of(context)!.saved,
    buttonText: "OK",
  ),
);
await editModel.addMemo();
await dialogResult;
await navigator;

コードAで警告が出ます。
同じ警告で解決してコードBができました。
コードBを参考にコードAを修正してください

すると// ignore: use_build_context_synchronouslyを挿入することを回答してきました。
先ほど言ったように使いたくないので、再び次のようにお願いします。

コメントで解決しない方法でお願いします

すると、次のように回答してきました。

SquareButton(
  text: "あ",
  onPressed: () {
    gojyuonItem(0).then((searchItem) {
      Navigator.push(
        context,
        MaterialPageRoute(
          builder: (context) => OrderPage(searchData: searchItem),
        ),
      );
    });
  },
),

asyncawaitではなくてthenを使った方法で回答でした。
まったくthenのことを思いもつきませんでした。
早速、適用すると見事動きました。

まとめると・・・

修正前と修正後を振り返ると・・・

修正前

onPressed: () async {
  final searchItem = await gojyuonItem(0);
  await Navigator.push(
    context,
    MaterialPageRoute(
      builder: (context) =>
    	    OrderPage(searchData: searchItem),
    ),
  );
},

修正後

onPressed: () {
  gojyuonItem(0).then((searchItem) {
    Navigator.push(
      context,
      MaterialPageRoute(
        builder: (context) =>
            OrderPage(searchData: searchItem),
      ),
    );
  });
},

非同期処理はasyncawaitしか使っていなくて、thenを使った方法はよく理解していませんでした。
thenを使った方法もひととおり確認しておかなくては行けませんね。

スマホアプリ「ひとこと投資メモ」シリーズをリリース中

Flutter学習のアウトプットの一環として「日本株ひとこと投資メモ」「米国株ひとこと投資メモ」を公開しています。

簡単に使えるライトな投資メモアプリです。
iPhone、Android両方に対応しています。
みなさんの投資ライフに少しでも活用していただきれば幸いです。
以下のリンクからそれぞれのサイトに移動してダウンロードをお願いします。
https://jpstockminimemo.arafipro.com/
https://usstockminimemo.arafipro.com/

GitHubで編集を提案

Discussion