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

Flutter中SharedPreferences初始化延迟引发LateInitializationError问题解决

解决SharedPreferences异步初始化导致的LateInitializationError问题

问题根源在于你用late修饰了_isEditingText和initialText,但这两个变量是在异步方法initializePreference中初始化的。Flutter会在initState执行后立刻调用build方法,此时异步操作还未完成,late变量还没被赋值,直接访问就会触发LateInitializationError,导致红屏。

下面是两种可行的解决方式:


方式一:使用可空变量+加载状态判断

把late修饰的变量改成可空类型,在build方法中先判断变量是否初始化完成,未完成时显示加载UI,避免直接访问未初始化的变量。

修改后的代码示例:

bool? _isEditingText;
TextEditingController _editingController = TextEditingController();
String? initialText;
SharedPreferences? _prefs;

@override
void initState(){
  super.initState();
  initializePreference();
}

Future<void> initializePreference() async{
  _prefs = await SharedPreferences.getInstance();
  String? name = _prefs?.getString('name');
  
  if (name == null) {
    _isEditingText = true;
    initialText = 'Enter ur name';
  } else {
    _isEditingText = false;
    initialText = name;
  }
  
  // 初始化完成后刷新UI,判断组件是否已挂载避免警告
  if(mounted) setState(() {});
}    

@override
Widget build(BuildContext context) {
  // 未初始化完成时显示加载组件
  if (_isEditingText == null || initialText == null) {
    return const Center(child: CircularProgressIndicator());
  }

  // 初始化完成后的正常页面UI
  return Scaffold(
    body: TextField(
      controller: _editingController..text = initialText!,
      enabled: _isEditingText!,
      // 其他TextField配置
    ),
  );
}

方式二:使用FutureBuilder管理异步状态

通过FutureBuilder监听异步初始化的状态,统一处理加载中、加载完成、加载失败的场景,代码结构更清晰。

修改后的代码示例:

late bool _isEditingText;
TextEditingController _editingController = TextEditingController();
late String initialText;
SharedPreferences? _prefs;
// 保存初始化的Future,避免每次build都重新执行异步操作
late Future<void> _initFuture;

@override
void initState(){
  super.initState();
  _initFuture = initializePreference();
}

Future<void> initializePreference() async{
  _prefs = await SharedPreferences.getInstance();
  String? name = _prefs?.getString('name');
  
  if (name == null) {
    _isEditingText = true;
    initialText = 'Enter ur name';
  } else {
    _isEditingText = false;
    initialText = name;
  }
}    

@override
Widget build(BuildContext context) {
  return FutureBuilder(
    future: _initFuture,
    builder: (context, snapshot) {
      if (snapshot.connectionState == ConnectionState.waiting) {
        // 加载中显示转圈
        return const Center(child: CircularProgressIndicator());
      } else if (snapshot.hasError) {
        // 加载失败显示错误提示
        return Center(child: Text('加载失败: ${snapshot.error}'));
      } else {
        // 加载完成显示正常UI
        return Scaffold(
          body: TextField(
            controller: _editingController..text = initialText,
            enabled: _isEditingText,
            // 其他TextField配置
          ),
        );
      }
    },
  );
}

关键注意点

  1. 无论哪种方式,都要确保在变量初始化完成前,不要让build方法访问未初始化的变量。
  2. 使用setState时建议加上if(mounted)判断,避免组件已销毁时调用setState引发警告。
  3. 方式二中的_initFuture要在initState中初始化,不要直接在FutureBuilder的future参数中写initializePreference(),否则每次build都会重新执行异步操作。

内容的提问来源于stack exchange,提问作者S.Beigi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 21:15:10