Flutter待办列表跳转报No MediaQuery及MaterialLocalizations错误求助
问题排查与解决方案
核心错误原因
- 全局启动逻辑放置错误:你将
runApp(Home())和Firebase初始化放在了Home页面组件的内部方法中,runApp是整个Flutter应用的入口方法,只能调用一次且必须放在全局main函数中,放在页面内部会导致应用组件层级完全错乱,上下文无法获取全局配置。 - 组件层级配置错误:
MaterialApp是应用的全局根组件,负责提供MediaQuery、MaterialLocalizations、导航器等全局能力,不能放在普通页面组件的build方法中返回,否则会出现嵌套应用实例、上下文不匹配的问题。 - 路由使用不规范:调用
Navigator.pushNamedAndRemoveUntil跳转到/路由前,没有在根MaterialApp中配置对应的路由表。
修复步骤
- 将Firebase初始化、
runApp逻辑移动到全局main.dart的入口函数中,将MaterialApp作为根组件配置。 - 清理
Home组件内部的启动逻辑,仅保留页面本身的业务代码,直接返回Scaffold即可。 - 调整路由跳转逻辑,要么在根
MaterialApp中配置路由表,要么替换为非命名路由的跳转方法。
完整修复代码
main.dart
import 'package:flutter/material.dart'; import 'package:firebase_core/firebase_core.dart'; import 'home.dart'; // 替换为你自己的Home文件路径 void main() async { WidgetsFlutterBinding.ensureInitialized(); await Firebase.initializeApp(); runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( title: '待办列表', theme: ThemeData.dark(), // 配置路由表,如果需要用命名路由的话 routes: { '/': (context) => const Home(), // 其他路由可以在这里添加 }, ); } }
home.dart(你的Home组件文件)
import 'package:flutter/material.dart'; import 'package:cloud_firestore/cloud_firestore.dart'; class Home extends StatefulWidget { const Home({Key? key}) : super(key: key); @override State<Home> createState() => _HomeState(); } class _HomeState extends State<Home> { late String _userToDo; List todoList = []; @override void initState() { super.initState(); todoList.addAll(['Milk', 'Car', 'Sugar']); } void _menuOpen() { Navigator.of(context).push( MaterialPageRoute(builder: (BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('Menu'),), body: Row( children: [ const Padding(padding: EdgeInsets.only(left: 15)), ElevatedButton(onPressed: () { Navigator.pop(context); // 因为已经在根MaterialApp配置了/路由,这里可以正常调用 Navigator.pushNamedAndRemoveUntil(context, '/', (route) => false); }, child: const Text('Home')), const Padding(padding: EdgeInsets.only(left: 15)), const Text('Home old') ], ) ); }) ); } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: Colors.grey[900], appBar: AppBar( title: const Text('Список дел'), actions: [ IconButton(onPressed: _menuOpen, icon: const Icon(Icons.menu_outlined), ) ], ), body: ListView.builder( itemCount: todoList.length, itemBuilder: (BuildContext context, int index){ return Dismissible( key: Key(todoList[index]), child: Card( child: ListTile( title: Text(todoList[index]), trailing: IconButton( icon: const Icon(Icons.delete_sweep, color: Colors.redAccent, ), onPressed: () { setState(() { todoList.removeAt(index); }); }, ) ), ), onDismissed: (direction) { setState(() { todoList.removeAt(index); }); }, ); } ), floatingActionButton: FloatingActionButton( backgroundColor: Colors.green, onPressed: () { showDialog(context: context, builder: (BuildContext context){ return AlertDialog( title: const Text('Добавить'), content: TextField( onChanged: (String value){ _userToDo = value; }, ), actions: [ ElevatedButton(onPressed: (){ FirebaseFirestore.instance.collection('items').add({'item': _userToDo}); setState(() { todoList.add(_userToDo); }); Navigator.of(context).pop(); }, child: const Text('Добавить') ) ], ); }); }, child: const Icon(Icons.add_comment_outlined, color: Colors.white, ), ), ); } }
额外优化说明
我在添加待办的逻辑里额外加了本地列表的更新操作,你之前的代码只把数据存到了Firestore,没有更新本地的todoList,所以添加后页面不会实时显示新的待办项,补充后就可以正常刷新了。
内容的提问来源于stack exchange,提问作者Юрий Ришко
相关产品推荐
相关产品推荐

