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

如何解决Flutter中Shared Preferences未初始化错误?

错误原因分析

你为_sharedPreferences添加了late修饰符,承诺它会在被访问前完成初始化,但问题出在initState中调用的_initializeData是异步方法——initState本身是同步执行的,不会等待异步操作完成就触发页面首次build。

当SharedPreferences.getInstance()的异步读取偶尔出现延迟(比如设备IO负载高、首次读取缓存),页面build会先于_sharedPreferences初始化完成,此时在build中访问_sharedPreferences.getString(ROLE)就会触发LateInitializationError,这就是错误偶发的核心原因。

修复方案(沿用现有逻辑)

我们可以新增一个状态标记跟踪SharedPreferences的初始化状态,在未完成前显示加载占位,避免访问未初始化的变量,具体修改如下:

1. 新增状态变量

在_QuizListPageState中添加布尔变量,标记SharedPreferences是否初始化完成:

bool _isSharedPrefsReady = false;

2. 更新初始化方法

在获取到SharedPreferences实例后,更新状态标记:

void _initializeData() async {
  _sharedPreferences = await SharedPreferences.getInstance();
  // 标记SharedPreferences已就绪
  setState(() {
    _isSharedPrefsReady = true;
  });
  _categoryService = CategoryService();
  setState(() {
    _areQuizzesLoaded = false;
  });
  await _loadCategories();
}

3. 修改build方法,添加初始化判断

在build中先判断初始化状态,未就绪时显示加载状态,就绪后再渲染完整UI:

@override
Widget build(BuildContext context) {
  final height = MediaQuery.of(context).size.height -
      AppBar().preferredSize.height -
      MediaQuery.of(context).padding.top -
      MediaQuery.of(context).padding.bottom;
  final width = MediaQuery.of(context).size.width;

  // 未初始化完成时显示加载占位
  if (!_isSharedPrefsReady) {
    return const Scaffold(
      body: Center(child: CircularProgressIndicator()),
    );
  }

  return Scaffold(
    appBar: AppBar(
      title: Text(widget.category.categoryTitle),
      actions: (_sharedPreferences.getString(ROLE) != ROLE_NORMAL)
          ? [
              Container(
                margin: const EdgeInsets.only(
                  top: 10,
                  right: 10,
                  left: 5,
                  bottom: 5,
                ),
                child: ElevatedButton(
                  onPressed: () {
                    Navigator.push(
                      context,
                      MaterialPageRoute(
                        builder: (context) => AddQuizPage(
                          userid: _sharedPreferences.getInt(USER_ID) ?? 0,
                          categoryid: widget.category.categoryId ?? 0,
                          token: _sharedPreferences.getString(BEARER_TOKEN) ??
                              'null',
                        ),
                      ),
                    );
                  },
                  child: const Text('Add Quiz'),
                ),
              ),
            ]
          : null,
    ),
    body: Container(
      child: const Text('Hello'),
    ),
  );
}

额外优化:合并加载状态判断

你可以将_isSharedPrefsReady和_areQuizzesLoaded合并,统一控制页面加载状态,避免多次setState导致的UI闪烁:

// build中的判断逻辑修改为
if (!_isSharedPrefsReady || !_areQuizzesLoaded) {
  return const Scaffold(
    body: Center(child: CircularProgressIndicator()),
  );
}

这样既保证了访问_sharedPreferences前它一定已初始化完成,又能给用户提供清晰的加载反馈,彻底解决偶发的未初始化错误。

内容的提问来源于stack exchange,提问作者ayush

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 17:50:45