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

Flutter技术求助:带SharedPreferences登录状态校验的启动页跳转异常问题咨询

问题分析与解决方案

看起来你的问题出在启动页的Timer和登录状态判断的时机不匹配,以及重复导航导致的页面重置。让我拆解一下问题根源,再给出修复方案:

问题根源

  1. 重复导航导致页面重置:你的代码里,Timer会在3秒后无条件执行_navigateUser方法。当用户已登录并进入/main页面后,3秒后这个Timer回调依然会触发,再次调用Navigator.pushReplacementNamed(context, "/main")——这会重新初始化/main页面,导致BottomNavigationBar回到默认的/home索引。

  2. 启动页未正常显示:原来的逻辑是等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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 17:32:30