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

Flutter中Navigator.push跳转后initState未执行问题求助

Flutter initState 不执行的问题排查与解决

我在Flutter中遇到initState方法完全不工作的问题——在initState里打印的"HELLO"没有输出,调用的_loadNightMode方法也没执行,导致无法从SharedPreferences读取夜间模式的布尔值,且没有任何错误提示。

相关代码

有问题的State代码

class _MyAppState extends State<MyApp> {
  late bool _nightMode;

  Future<void> _loadNightMode() async {
    final prefs = await SharedPreferences.getInstance();
    setState(() {
      _nightMode = (prefs.getBool('nightMode') ?? false);
    });
  }

  @override
  void initState() {
    super.initState();
    _loadNightMode();
    print("HELLO");
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData.light(),
      darkTheme: ThemeData.dark(),
      themeMode: _nightMode ? ThemeMode.dark : ThemeMode.light,
      debugShowCheckedModeBanner: false,
      home: const LandingPage(),
    );
  }
}

调用MyApp的方式

logout() {
  FirebaseAuth.instance.signOut();
  Navigator.of(context).push(
    MaterialPageRoute(
      builder: (BuildContext context) {
        return const MyApp();
      },
    ),
  );
}

问题根源

你把MaterialApp作为普通路由页面用Navigator.push推入现有导航栈是错误的——MaterialApp是整个应用的根组件,它内部维护了自己的导航器(Navigator)。当你嵌套另一个MaterialApp到现有导航栈时,新的MaterialApp的State生命周期会出现异常,导致initState无法正常触发。

另外,使用const MyApp()创建实例的方式,在嵌套场景下会加剧上下文冲突,进一步阻碍状态初始化。

修复方案

1. 替换路由并清空栈

退出登录后,应该用pushAndRemoveUntil清空之前的所有路由,让MyApp作为新的根组件初始化,而不是推入新路由:

logout() async {
  await FirebaseAuth.instance.signOut();
  // 清空所有历史路由,替换为MyApp
  Navigator.of(context).pushAndRemoveUntil(
    MaterialPageRoute(builder: (context) => const MyApp()),
    (Route<dynamic> route) => false,
  );
}

pushAndRemoveUntil会确保新的MyApp完全接管应用,其State生命周期能正常执行。

2. 避免嵌套MaterialApp

整个应用只保留一个MaterialApp作为根组件,如果需要切换主题,把主题逻辑放到MaterialApp内部的子组件中,不要重新创建MaterialApp实例。

3. 增加错误捕获(可选)

给_loadNightMode添加错误捕获,避免读取SharedPreferences时静默失败:

Future<void> _loadNightMode() async {
  try {
    final prefs = await SharedPreferences.getInstance();
    setState(() {
      _nightMode = prefs.getBool('nightMode') ?? false;
    });
  } catch (e) {
    print('加载夜间模式失败: $e');
    setState(() {
      _nightMode = false;
    });
  }
}

验证修复

修改路由跳转方式后,重新运行应用,退出登录时MyApp的initState会正常执行,控制台会输出"HELLO",_loadNightMode也能正确读取SharedPreferences中的值。

内容的提问来源于stack exchange,提问作者ronie arnibal

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 18:31:07