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

Flutter启动页自动登录异常:始终跳转至登录页面求助

Flutter启动页自动登录逻辑问题排查

核心问题分析

1. 登录凭证硬编码,未使用SharedPreferences存储的值

你的signInWithEmailAndPassword方法里直接传了字符串字面量'email'和'password',而非从SharedPreferences获取的实际凭证,这会导致每次都用无效信息登录,必然触发错误分支。

2. 异步操作未等待,导致获取的凭证无效

  • sharedPrefInit()是异步方法,调用时未加await,可能SharedPreferences还没完成初始化就去获取凭证,导致拿不到正确值
  • getCred('email')和getCred('password')返回的是Future<String>,你直接把Future对象赋值给变量,未用await获取实际字符串值,打印的$email其实是Future实例的描述,不是真实邮箱

3. catchError逻辑完全错误

signInWithEmailAndPassword登录成功时会走then回调,不会进入catchError。你把登录成功后的跳转逻辑放在catchError里的errMsg == null分支,这永远不会触发——因为只有登录失败时才会进入catchError,此时errMsg必然不为null,所以每次都会走到else分支跳转到登录页。

4. SharedPreferences类的细节问题

  • reset()方法内部有await操作,但返回值是void,应改为Future<void>,否则调用时无法等待清除操作完成
  • getCred()方法中,如果prefs.getString(key)为null,toString()会得到字符串"null",这会导致用"null"作为邮箱/密码去登录,需要处理null场景

修正后的代码

启动页initState修正

@override
void initState() {
  super.initState();
  Timer(const Duration(seconds: 3), () async {
    // 等待SharedPreferences初始化完成
    await sharedPreference().sharedPrefInit();
    
    // 等待获取实际的邮箱和密码
    String? email = await sharedPreference().getCred('email');
    String? password = await sharedPreference().getCred('password');
    print('Email: $email\nPassword $password');

    // 先判断凭证是否为空,避免无效登录请求
    if (email == null || password == null || email.isEmpty || password.isEmpty) {
      await sharedPreference().reset();
      _navigateToLogin();
      return;
    }

    try {
      // 使用获取到的凭证登录
      await firebaseAuth.signInWithEmailAndPassword(email: email, password: password);
      // 登录成功,跳转首页
      Navigator.pushAndRemoveUntil(
        context,
        PageRouteBuilder(
          transitionDuration: const Duration(seconds: 1),
          transitionsBuilder: (context, animation, animationTime, child) {
            animation = CurvedAnimation(
                parent: animation, curve: Curves.fastLinearToSlowEaseIn);
            return ScaleTransition(
              scale: animation,
              alignment: Alignment.center,
              child: child,
            );
          },
          pageBuilder: (context, animation, animationTime) {
            return HomeScreen(email: email);
          },
        ),
        (route) => false,
      );
    } catch (errMsg) {
      // 登录失败,重置SharedPreferences并跳转登录页
      print('登录失败: $errMsg');
      await sharedPreference().reset();
      _navigateToLogin();
    }
  });
}

// 抽离跳转登录页逻辑,避免重复代码
void _navigateToLogin() {
  Navigator.pushReplacement(
    context,
    PageRouteBuilder(
      transitionDuration: const Duration(seconds: 1),
      transitionsBuilder: (context, animation, animationTime, child) {
        animation = CurvedAnimation(
            parent: animation, curve: Curves.fastLinearToSlowEaseIn);
        return ScaleTransition(
          scale: animation,
          alignment: Alignment.center,
          child: child,
        );
      },
      pageBuilder: (context, animation, animationTime) {
        return const LoginOrSignUp();
      },
    ),
  );
}

SharedPreferences类修正

import 'package:shared_preferences/shared_preferences.dart';

class sharedPreference {
  Future<void> sharedPrefInit() async {
    try {
      final SharedPreferences prefs = await SharedPreferences.getInstance();
      prefs.getString("recipedia");
    } catch (err) {
      SharedPreferences.setMockInitialValues({});
      final SharedPreferences prefs = await SharedPreferences.getInstance();
      prefs.setString("recipedia", "my-app");
    }
  }

  Future<void> saveCred({required String email, required String password}) async {
    final SharedPreferences prefs = await SharedPreferences.getInstance();
    await prefs.setString("email", email);
    await prefs.setString("password", password);
  }

  Future<String?> getCred(String key) async {
    final SharedPreferences prefs = await SharedPreferences.getInstance();
    // 直接返回null,避免将null转为"null"字符串
    return prefs.getString(key);
  }

  // 修改返回值为Future<void>,支持await等待清除完成
  Future<void> reset() async {
    final SharedPreferences prefs = await SharedPreferences.getInstance();
    await prefs.clear();
  }
}

额外建议

  • 不要每次都创建sharedPreference()实例,可以在类中定义单例,避免重复初始化
  • 可去掉启动页的固定3秒等待,改为等待初始化和登录请求完成后立即跳转,提升用户体验

内容的提问来源于stack exchange,提问作者Mr Fin

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 19:35:28