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

Flutter使用SharedPreferences追加数据时触发空检查运算符错误

解决SharedPreferences追加列表时的_CastError问题

错误原因

你触发的_CastError是因为首次调用add()方法时,SharedPreferences中还不存在todo_title和todo_detail这两个键,getStringList()会返回null,但你用了!强制解包null值,直接引发崩溃。

修复后的add()方法

处理null场景,用空合并运算符??在列表为null时初始化空列表,避免强制解包:

void add() async {
  final title1 = add_title_controller.text;
  final detail1 = add_detail_controller.text;
  final pref = await SharedPreferences.getInstance();
  
  // 若获取的列表为null,自动初始化空列表
  final List<String> todoTitle = pref.getStringList('todo_title') ?? [];
  final List<String> todoDetail = pref.getStringList('todo_detail') ?? [];
  
  todoTitle.add(title1);
  todoDetail.add(detail1);
  
  // 等待数据持久化完成
  await pref.setStringList('todo_title', todoTitle);
  await pref.setStringList('todo_detail', todoDetail);
}

用ListView.builder展示数据

要展示存储的数据,需先从SharedPreferences加载,再结合ListView.builder构建列表:

class TodoPage extends StatefulWidget {
  const TodoPage({super.key});

  @override
  State<TodoPage> createState() => _TodoPageState();
}

class _TodoPageState extends State<TodoPage> {
  List<String> _todoTitles = [];
  List<String> _todoDetails = [];
  final TextEditingController add_title_controller = TextEditingController();
  final TextEditingController add_detail_controller = TextEditingController();

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

  // 加载本地存储的待办数据
  Future<void> _loadTodoData() async {
    final pref = await SharedPreferences.getInstance();
    setState(() {
      _todoTitles = pref.getStringList('todo_title') ?? [];
      _todoDetails = pref.getStringList('todo_detail') ?? [];
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('待办清单')),
      body: Column(
        children: [
          // 输入区域
          Padding(
            padding: const EdgeInsets.all(8.0),
            child: Column(
              children: [
                TextField(
                  controller: add_title_controller,
                  decoration: const InputDecoration(hintText: '输入标题'),
                ),
                TextField(
                  controller: add_detail_controller,
                  decoration: const InputDecoration(hintText: '输入详情'),
                ),
                ElevatedButton(
                  onPressed: () async {
                    await add();
                    // 添加完成后刷新列表
                    await _loadTodoData();
                    // 清空输入框
                    add_title_controller.clear();
                    add_detail_controller.clear();
                  },
                  child: const Text('添加'),
                )
              ],
            ),
          ),
          // 列表展示区域
          Expanded(
            child: ListView.builder(
              itemCount: _todoTitles.length,
              itemBuilder: (context, index) {
                return ListTile(
                  title: Text(_todoTitles[index]),
                  subtitle: Text(_todoDetails[index]),
                );
              },
            ),
          )
        ],
      ),
    );
  }

  // 修复后的add方法
  Future<void> add() async {
    final title1 = add_title_controller.text;
    final detail1 = add_detail_controller.text;
    final pref = await SharedPreferences.getInstance();
    
    final List<String> todoTitle = pref.getStringList('todo_title') ?? [];
    final List<String> todoDetail = pref.getStringList('todo_detail') ?? [];
    
    todoTitle.add(title1);
    todoDetail.add(detail1);
    
    await pref.setStringList('todo_title', todoTitle);
    await pref.setStringList('todo_detail', todoDetail);
  }
}

关键注意点

  • 调用setStringList()时加await,确保数据完全持久化后再执行后续操作
  • 添加数据后必须调用_loadTodoData()刷新UI,否则列表不会更新
  • 确保输入控制器已正确初始化,避免获取空文本

内容的提问来源于stack exchange,提问作者HARSH J.

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 21:11:39