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

Flutter启动页集成SharedPreferences遇late初始化错误求助

解决Flutter中SharedPreferences延迟初始化错误及启动页逻辑优化

问题根源分析

你的代码存在几个关键问题导致延迟初始化错误:

  • 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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 13:05:19