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が有効かどうか確認 |
最後までご覧いただき、ありがとうございました。