Flutter启动页集成SharedPreferences遇late初始化错误求助
问题根源分析
你的代码存在几个关键问题导致延迟初始化错误:
SharedPrefService.init()方法里出现无限递归调用(自己调用自己),导致无法正确初始化pref- 在
_SplashScreenState的成员变量声明阶段直接访问SharedPrefService.pref,此时pref还未完成初始化 - 初始化顺序混乱,既在
initState里直接赋值pref,又调用SharedPrefService.init(),逻辑冲突
修复方案及代码调整
1. 重构SharedPrefService类
修正初始化逻辑,确保pref只被初始化一次,避免递归:
class SharedPrefService { static late SharedPreferences _pref; // 初始化SharedPreferences,确保只执行一次 static Future<void> init() async { _pref = await SharedPreferences.getInstance(); } // 提供便捷的获取方法,避免直接暴露_pref static SharedPreferences get instance => _pref; }
2. 调整SplashScreen的状态逻辑
- 不在成员变量声明时直接访问SharedPreferences,改为在异步初始化后赋值
- 确保
SharedPrefService.init()完成后再读取数据、执行后续逻辑 - 修正
initState的执行顺序(super.initState()必须放在最前面)
class _SplashScreenState extends State<SplashScreen> { String playerId = ''; var usrEmail; String usrname = ''; @override void initState() { super.initState(); // 必须放在initState的第一行 _initializeApp(); } // 统一处理初始化逻辑 Future<void> _initializeApp() async { // 先初始化SharedPreferences await SharedPrefService.init(); // 读取本地存储的用户数据 usrEmail = SharedPrefService.instance.getString('email'); usrname = SharedPrefService.instance.getString('username') ?? ''; // 初始化OneSignal 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; if (osUserID != null) { setState(() { playerId = osUserID; }); print('The player id from main.dart ...........${osUserID}'); print('this.playerid from main.dart ${playerId}'); } } Future<void> _navigateToHome() async { await Future.delayed(const Duration(milliseconds: 1500)); Navigator.pushReplacement( context, MaterialPageRoute( builder: (context) => usrEmail == null ? const LoginPage() : homePageAdmin(playerId, usrname), ), ); } @override Widget build(BuildContext context) { return const Scaffold( body: Center( child: Text( 'Splash Screen', style: TextStyle( fontSize: 25, fontWeight: FontWeight.bold, color: Colors.blueAccent), ), ), ); } }
3. 可选:在main函数提前初始化
如果希望整个App启动时就完成SharedPreferences初始化,可以修改main.dart的入口:
void main() async { WidgetsFlutterBinding.ensureInitialized(); // 必须加这句,确保Flutter引擎初始化完成 await SharedPrefService.init(); runApp(const MyApp()); }
这样后续页面可以直接使用SharedPrefService.instance,无需重复初始化。
关键注意事项
late修饰的变量必须在使用前完成初始化,否则会抛出LateInitializationError- 异步初始化逻辑要统一放在
initState内的异步方法中,不要直接在initState上标记async(虽然语法允许,但可能导致生命周期问题) - 读取SharedPreferences数据时要处理
null情况,避免调用toString()导致空指针(比如用?? ''设置默认值)
内容的提问来源于stack exchange,提问作者Minal Suryawanshi
相关产品推荐
相关产品推荐

