使用rflutter_alert包出现No MaterialLocalizations错误如何解决
问题解决方法
错误根因
你调用Alert.show()时使用的BuildContext是QuizApp组件自身的上下文,而MaterialApp是在QuizApp的build方法中才被创建返回的,这个父级上下文不包含MaterialApp提供的MaterialLocalizations本地化资源,因此rflutter_alert弹窗组件初始化时找不到所需资源抛出错误。
解决方案(推荐第一种,改动最小)
方案1:调整MaterialApp层级,将其移到应用根节点
- 修改main函数,把MaterialApp放到runApp的根层级,将QuizApp作为MaterialApp的home参数传入
- 删除QuizApp的build方法中包裹Scaffold的MaterialApp外层,直接返回Scaffold即可
对应修改代码如下:
// 修改后的main函数 void main() { runApp( MaterialApp( debugShowCheckedModeBanner: false, home: const QuizApp(), ), ); } // 修改后的QuizApp build方法 @override Widget build(BuildContext context) { return Scaffold( backgroundColor: Colors.black, body: SafeArea( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ // 此处保留你原有的所有子组件代码,完全不需要修改 Expanded( flex: 5, child: Center( child: Text( quizObject.getquestiontext(), textAlign: TextAlign.center, style: TextStyle( fontSize: 30, color: Colors.white, ), ), ), ), Expanded( child: Padding( padding: const EdgeInsets.all(15.0), child: TextButton( onPressed: () { checkAnswer(true); }, style: TextButton.styleFrom( backgroundColor: Colors.green, ), child: Center( child: Text( 'True', style: TextStyle( fontSize: 20, color: Colors.white, ), ), ), ), ), ), Expanded( child: Padding( padding: const EdgeInsets.all(15.0), child: TextButton( onPressed: () { checkAnswer(false); }, style: TextButton.styleFrom( backgroundColor: Colors.red, ), child: Center( child: Text( 'False', style: TextStyle( fontSize: 20, color: Colors.white, ), ), ), ), ), ), Row( children: scorekeeper, ), ], ), ), ); }
方案2:不调整组件层级,使用Builder获取子上下文
如果不想改动现有组件结构,可以在MaterialApp的home参数处用Builder包裹Scaffold,使用Builder提供的子上下文调用弹窗:
@override Widget build(BuildContext context) { return MaterialApp( debugShowCheckedModeBanner: false, // 用Builder包裹Scaffold获取子上下文 home: Builder( builder: (childContext) { return Scaffold( // 原有Scaffold内容不变 backgroundColor: Colors.black, body: SafeArea( // ... 原有子组件代码 ), ); } ), ); }
修改checkAnswer方法中调用Alert时的context为childContext即可。
优化建议
原代码中弹窗调用后直接执行重置逻辑,可能出现弹窗还未展示就被重置的问题,建议将重置逻辑放到Alert的onClose回调中:
if (quizObject.isfinished() == true) { Alert( context: context, title: 'Warning', desc: 'You have reached the end of the questions', onClose: () { setState(() { quizObject.reset(); scorekeeper = []; }); } ).show(); }
内容的提问来源于stack exchange,提问作者stackusar
相关产品推荐
相关产品推荐

