⛳
【Flutter】Appクラスでcontextを使う方法 〜 'No MaterialLocalizations found.'を解決する〜
今回はAppクラスでcontextを使う方法を紹介します。
先日強制アップデート機能を実装するに当たって困ったことがありました。AppクラスのinitState内で、contextを使おうとするとエラーが出てきました。
FlutterError (No MaterialLocalizations found.
MyApp widgets require MaterialLocalizations to be provided by a Localizations widget ancestor.
The material library uses Localizations to generate messages, labels, and abbreviations.
To introduce a MaterialLocalizations, either use a MaterialApp at the root of your application to include them automatically, or add a Localization widget with a MaterialLocalizations delegate.
The specific widget that could not find a MaterialLocalizations ancestor was:
MyApp
The ancestors of this widget were:
[root])
日本語訳です。ChatGPT先生ありがとうございます。
Flutterエラー(MaterialLocalizationsが見つかりません。
MyAppウィジェットには、Localizationsウィジェットの祖先から提供されたMaterialLocalizationsが必要です。
マテリアルライブラリは、メッセージ、ラベル、略語を生成するためにLocalizationsを使用します。
MaterialLocalizationsを導入するには、自動的にそれらを含めるためにアプリケーションのルートにMaterialAppを使用するか、MaterialLocalizationsデリゲートを持つLocalizationウィジェットを追加します。
MaterialLocalizations祖先が見つからなかった特定のウィジェットは:
MyApp
このウィジェットの祖先は次のとおりでした:
[root])
その解決方法をまとめました。
サンプル
起動時にDialogを出します。Appクラス以降の通常は最初の画面で使えばいいのですが、全画面にわたってlistenさせたい、StatefullConsumerを使いたいなどの理由があり、実装していました。その辺の詳細は割愛します。
サンプルコード
mport 'package:flutter/material.dart';
void main() {
// runApp(const MyApp());
runApp(const MaterialApp(home: MyApp())); // MaterialAppで先にラップする
}
class MyApp extends StatefulWidget {
const MyApp({super.key});
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((timeStamp) async {
await Future.delayed(const Duration(seconds: 3));
if (mounted) {
showDialog<void>(
context: context,
builder: (context) => const SampleDialog(),
);
}
});
}
Widget build(BuildContext context) {
return const MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
body: Center(
child: MyWidget(),
),
),
);
}
}
class MyWidget extends StatelessWidget {
const MyWidget({super.key});
Widget build(BuildContext context) {
return Text(
'Hello, World!',
style: Theme.of(context).textTheme.headlineMedium,
);
}
}
class SampleDialog extends StatelessWidget {
const SampleDialog({super.key});
Widget build(BuildContext context) {
return const AlertDialog(title: Text('This is sample'));
}
}
解決方法 MyAppをMaterialAppでさらにラップ
どうやら、使用するMyappクラスの前にMaterialAppを使わないといけなかったようです。
このように修正すればOK!
void main() {
// runApp(const MyApp()); 修正前
runApp(const MaterialApp(home: MyApp())); // 修正後
}
参考はこちら
まとめ
当初悩みましたが、よくエラー文読めば意外と簡単に対処できました。
他に良い解決策もあるかもしれませんが、もし情報ありましたらいただけると幸いです。
参考資料
Discussion