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

Flutter登录场景下Shared Preferences失效问题排查求助

问题排查与修复方案

核心问题分析

  1. SharedPrefService初始化死循环
    SharedPrefService.init()方法内部递归调用自身,导致永远无法执行到SharedPreferences.getInstance(),pref实例始终为null:

    static Future<void> init() async {
      await SharedPrefService.init(); // 此处无限递归,阻塞初始化流程
      SharedPrefService.pref = await SharedPreferences.getInstance();
    }
    
  2. 未触发SharedPreferences初始化
    在_SplashScreenState的initState中,没有调用SharedPrefService.init(),导致pref从未被赋值,自然无法读取存储的用户信息。

  3. 异步逻辑未同步等待
    _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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 20:50:26