You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter待办列表跳转报No MediaQuery及MaterialLocalizations错误求助

问题排查与解决方案

核心错误原因

  • 全局启动逻辑放置错误:你将runApp(Home())和Firebase初始化放在了Home页面组件的内部方法中,runApp是整个Flutter应用的入口方法,只能调用一次且必须放在全局main函数中,放在页面内部会导致应用组件层级完全错乱,上下文无法获取全局配置。
  • 组件层级配置错误:MaterialApp是应用的全局根组件,负责提供MediaQuery、MaterialLocalizations、导航器等全局能力,不能放在普通页面组件的build方法中返回,否则会出现嵌套应用实例、上下文不匹配的问题。
  • 路由使用不规范:调用Navigator.pushNamedAndRemoveUntil跳转到/路由前,没有在根MaterialApp中配置对应的路由表。

修复步骤

  1. 将Firebase初始化、runApp逻辑移动到全局main.dart的入口函数中,将MaterialApp作为根组件配置。
  2. 清理Home组件内部的启动逻辑,仅保留页面本身的业务代码,直接返回Scaffold即可。
  3. 调整路由跳转逻辑,要么在根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,提问作者Юрий Ришко

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.23 21:15:01