Flutter:物理设备SharedPreferences会话保持失效,模拟器正常
问题分析与修复方案
你的代码存在两个核心问题,导致物理设备上重启/切换后台后无法恢复登录状态:
1. 异步初始化未触发UI重建
CheckLoginUusuario是异步方法,initState调用它时不会等待执行完成,首次build时islogin仍为null,直接显示登录页。即使后续从SharedPreferences拿到了true,也没有调用setState通知Flutter更新UI。
2. 服务类中SharedPreferences初始化错误
ValidarLoginServices类里直接在成员变量位置写SharedPreferences prefs = await SharedPreferences.getInstance();是非法的——类成员初始化不能使用await,会导致prefs实例获取失败,登录状态可能无法正确存入。
修正后的代码
登录页面(Frm_Login)
class Frm_Login extends State<frm_Login> { bool? islogin; Future<void> CheckLoginUusuario() async { SharedPreferences prefs = await SharedPreferences.getInstance(); bool? loginState = prefs.getBool("CheckEstadoLogin"); // 获取状态后触发UI重建 setState(() { islogin = loginState; }); } @override void initState() { super.initState(); CheckLoginUusuario(); } @override Widget build(BuildContext context) { // 状态未获取完成时显示加载组件 if (islogin == null) { return const Center(child: CircularProgressIndicator()); } return islogin == true ? const MenuPrincipal() : LoginPage( child: TextButton( onPressed: () { if (KeyFormValidaciones.currentState?.validate() ?? false) { validarLoginservices.ValidarLogin(Contrasena.text, Usuario.text, context); } }, child: const Text("Login", style: TextStyle(fontSize: 25, color: Colors.white)), ), ); } }
登录验证服务类(ValidarLoginServices)
class ValidarLoginServices { Future<void> ValidateLogin(String ContrasenaLogin, String CorreoLogin, BuildContext context) async { // 移到方法内部获取SharedPreferences实例 SharedPreferences prefs = await SharedPreferences.getInstance(); // 替换为你的账号密码验证逻辑 if (ContrasenaLogin.isNotEmpty && CorreoLogin.isNotEmpty) { await prefs.setBool("CheckEstadoLogin", true); Navigator.of(context).pushAndRemoveUntil( MaterialPageRoute(builder: (context) => const MenuPrincipal()), (route) => false ); } } }
额外优化建议
- 可以在启动页(SplashScreen)完成登录状态检查,再跳转对应页面,用户体验更流畅。
- 给SharedPreferences的key定义常量,避免拼写错误:
const String loginStateKey = "CheckEstadoLogin";
内容的提问来源于stack exchange,提问作者Anes
相关产品推荐
相关产品推荐

