Flutter使用SharedPreferences追加数据时触发空检查运算符错误
错误原因
你触发的_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.
相关产品推荐
相关产品推荐

