Flutterアプリ開発中に、非同期処理後の BuildContext
の使用でエラーが発生したことはありませんか?
この記事では、BuildContext
の使用に関するエラーを防ぐための具体的な対処法・ベストプラクティスを初心者にもわかりやすく解説します。画面遷移やスナックバー表示でクラッシュを回避するためにも、ぜひご一読ください。
目次
BuildContextについて
BuildContextとは?
BuildContext
とは、Flutterのウィジェットツリー内の位置情報を表すオブジェクトで、Navigator
や ScaffoldMessenger
などの呼び出しに必要不可欠です。
ただし、非同期処理(await
)の後に誤って BuildContext
を使うと、すでに画面が破棄(dispose)されていてエラーになることがあります。
よくあるエラー例
以下は、BuildContext
に関するエラーの、汎用的なエラー構文です。
{
"resource": "ファイルパス/ファイル名.dart",
"owner": "診断コレクタ名",
"code": {
"value": "エラーコード",
"target": {
"$mid": 1,
"path": "エラーコードのドキュメントURLのパス",
"scheme": "https",
"authority": "エラーコードのドキュメントのドメイン"
}
},
"severity": エラーレベル (例: 1=エラー, 2=警告),
"message": "エラーメッセージ: 'BuildContext' を非同期ギャップをまたいで使用しないでください。関連性のない 'mounted' チェックでガードされています。\n'State.context' の使用は State の 'mounted' チェックで、その他の 'BuildContext' の使用は BuildContext の 'mounted' チェックでガードしてください。",
"source": "発生源 (例: dart)",
"startLineNumber": エラー開始行,
"startColumn": エラー開始列,
"endLineNumber": エラー終了行,
"endColumn": エラー終了列
}
安全なBuildContextの使い方
非同期処理後の安全な書き方
if (!mounted) return;
await someAsyncOperation();
if (mounted && context.mounted) {
Navigator.of(context).push(...);
ScaffoldMessenger.of(context).showSnackBar(...);
}
mounted
:Stateがまだ画面に存在するかどうかを示すフラグ。
context.mounted
:Flutter 3.7以降で導入された、より明示的な BuildContext
の有効性チェック。
修正が必要な主なケース
以下のようなメソッドやウィジェットは、非同期処理後に使う場合に注意が必要です。
Navigator.of(context)
ScaffoldMessenger.of(context)
Theme.of(context)
MediaQuery.of(context)
いずれも BuildContext
に依存しているため、画面が破棄された後に使うとエラーになります。
チェックすべきタイミング
await
直後- 非同期処理の結果を使う前
Navigator
を使った画面遷移の前ScaffoldMessenger
でスナックバーを出す前
よく使うパターン
パターン1:簡単な遷移処理
if (mounted && context.mounted) {
Navigator.of(context).pop();
}
パターン2:エラーハンドリングと併用
try {
await someAsyncOperation();
} catch (e) {
if (mounted && context.mounted) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('エラーが発生しました')),
);
}
}
パターン3:複数の非同期処理を行うとき
await operation1();
if (!mounted) return;
await operation2();
if (mounted && context.mounted) {
Navigator.of(context).push(...);
}
結論
ベストプラクティス
- 非同期処理の前に
mounted
を確認 - 非同期処理の後に
mounted && context.mounted
を確認 - エラー処理の際にも忘れずにチェック
- 複数の非同期処理がある場合は各ステップで確認
避けるべきNGパターン
// NG①: チェックなしで使用
await someAsyncOperation();
Navigator.of(context).pop(); // → エラーの原因
// NG②: mountedだけをチェック
await someAsyncOperation();
if (mounted) {
Navigator.of(context).pop(); // → 不完全なチェック
// NG③: 非同期処理前にBuildContextを使用
Navigator.of(context).pop();
await someAsyncOperation(); // → 操作順が逆
まとめ
Flutterでは、非同期処理後の BuildContext
の安全性を意識することが、アプリの安定性とクラッシュ回避につながります。
処理のタイミング | チェックすべきこと |
---|---|
非同期処理の前 | mounted |
非同期処理の後 | mounted && context.mounted |
スナックバーや遷移時 | BuildContext が有効かどうか確認 |
最後までご覧いただき、ありがとうございました。