Flutter登录场景下Shared Preferences失效问题排查求助
问题排查与修复方案
核心问题分析
SharedPrefService初始化死循环
SharedPrefService.init()方法内部递归调用自身,导致永远无法执行到SharedPreferences.getInstance(),pref实例始终为null:static Future<void> init() async { await SharedPrefService.init(); // 此处无限递归,阻塞初始化流程 SharedPrefService.pref = await SharedPreferences.getInstance(); }未触发SharedPreferences初始化
在_SplashScreenState的initState中,没有调用SharedPrefService.init(),导致pref从未被赋值,自然无法读取存储的用户信息。异步逻辑未同步等待
_navigateToHome没有等待SharedPrefService.init()和initPlatformState完成就执行跳转,可能导致取到的usrEmail、playerId为空,同时逻辑执行顺序混乱。
修复后的完整代码
import 'package:flutter/material.dart'; import 'package:onesignal_flutter/onesignal_flutter.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'View/LoginPage.dart'; import 'View/homePageAdmin.dart'; class SplashScreen extends StatefulWidget { @override State<SplashScreen> createState() => _SplashScreenState(); } class SharedPrefService { static SharedPreferences? pref; static Future<void> init() async { // 移除递归调用,直接初始化SharedPreferences实例 SharedPrefService.pref = await SharedPreferences.getInstance(); } } class _SplashScreenState extends State<SplashScreen> { String playerId = ''; @override void initState() { super.initState(); // 统一处理所有异步初始化逻辑,确保执行顺序 _initServicesAndNavigate(); } // 按顺序执行初始化,避免竞态问题 Future<void> _initServicesAndNavigate() async { // 先初始化SharedPreferences await SharedPrefService.init(); // 再初始化OneSignal并获取playerId await initPlatformState(); // 最后执行跳转逻辑 await _navigateToHome(); } Future<void> initPlatformState() async { OneSignal.shared.setAppId('e89acaa4-5388-4e3a-bd69-44d197bdcbd7'); final status = await OneSignal.shared.getDeviceState(); final String? osUserID = status?.userId; print('The player id from main.dart ...........${osUserID}'); setState(() { // 处理null情况,避免空指针崩溃 this.playerId = osUserID ?? ''; }); print('this.playerid from main.dart ${this.playerId}'); } Future<void> _navigateToHome() async { await Future.delayed(const Duration(milliseconds: 1500)); final usrname = SharedPrefService.pref?.getString('username'); final usrEmail = SharedPrefService.pref?.getString('email'); final pId = this.playerId; Navigator.pushReplacement( context, MaterialPageRoute( builder: (context) => usrEmail == null ? const LoginPage() : homePageAdmin( pId, usrname ?? '', // 处理username为空的情况 ), ), ); } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: Colors.orangeAccent, body: Center( child: Container( decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(5), ), height: MediaQuery.of(context).size.height * 0.13, width: MediaQuery.of(context).size.width * 0.5, child: Image.asset('assets/image/AtDocHublogo.png'), ), ), ); } }
额外优化说明
- 改用
Image.asset替代冗余的Image构造,简化代码。 - 为
playerId和username添加null安全处理,避免空指针崩溃。 - 将分散的异步操作合并到统一方法中,确保初始化顺序,解决竞态问题。
内容的提问来源于stack exchange,提问作者Minal Suryawanshi
相关产品推荐
相关产品推荐

