Flutter技术求助:带SharedPreferences登录状态校验的启动页跳转异常问题咨询
问题分析与解决方案
看起来你的问题出在启动页的Timer和登录状态判断的时机不匹配,以及重复导航导致的页面重置。让我拆解一下问题根源,再给出修复方案:
问题根源
重复导航导致页面重置:你的代码里,Timer会在3秒后无条件执行
_navigateUser方法。当用户已登录并进入/main页面后,3秒后这个Timer回调依然会触发,再次调用Navigator.pushReplacementNamed(context, "/main")——这会重新初始化/main页面,导致BottomNavigationBar回到默认的/home索引。启动页未正常显示:原来的逻辑是等3秒后才去获取登录状态,这其实颠倒了顺序。如果登录状态获取很快,但Timer要等3秒,启动页应该会显示3秒;但如果你的主入口代码里提前判断了登录状态并直接跳转,就会跳过启动页。不过结合你提到的3秒后页面重置的现象,核心问题还是Timer的重复导航。
修复代码
修改你的SplashScreenPage,把登录状态判断和等待逻辑合并,确保只执行一次导航,并且在导航前确认页面还未被销毁:
import 'dart:async'; import 'package:flutter/material.dart'; import 'package:flutter_spinkit/flutter_spinkit.dart'; import 'package:shared_preferences/shared_preferences.dart'; class SplashScreenPage extends StatefulWidget { const SplashScreenPage({Key? key}) : super(key: key); @override State<SplashScreenPage> createState() => _SplashScreenPageState(); } class _SplashScreenPageState extends State<SplashScreenPage> { bool isLoggedIn = false; @override void initState() { super.initState(); // 合并登录状态检查和导航逻辑 _checkLoginAndNavigate(); } void _checkLoginAndNavigate() async { // 先获取登录状态 SharedPreferences prefs = await SharedPreferences.getInstance(); isLoggedIn = prefs.getBool('isLoggedIn') ?? false; // 确保启动页至少显示3秒(如果获取状态花了1秒,就再等2秒) await Future.delayed(const Duration(seconds: 3)); // 必须判断页面是否还挂载,防止已销毁的context被使用 if (!mounted) return; // 只执行一次导航 if (isLoggedIn) { Navigator.pushReplacementNamed(context, "/main"); } else { Navigator.pushReplacementNamed(context, "/login"); } } @override Widget build(BuildContext context) { return Scaffold( body: Padding( padding: const EdgeInsets.all(128), child: Column( mainAxisAlignment: MainAxisAlignment.center, mainAxisSize: MainAxisSize.max, children: const [ SpinKitFoldingCube( color: Colors.blue, size: 50.0, ) ], ), ), ); } }
额外建议
- 检查你的主入口(
main.dart)代码,确保没有提前判断登录状态并跳过启动页的逻辑。如果有,建议把所有导航判断都放在启动页里,保持逻辑统一。 - 导航时使用
pushReplacementNamed是正确的,它会替换当前路由栈,避免用户返回启动页。
内容的提问来源于stack exchange,提问作者willypede
相关产品推荐
相关产品推荐

