Flutter滑动删除本地存储数据后热重启恢复的问题求助
Flutter 待办应用删除数据不持久化问题修复
问题诊断
- 删除操作未持久化到本地存储:滑动删除时仅修改了内存中的
todoList,但没有将更新后的列表写入SharedPreferences,导致热重启后从本地读取旧数据,已删除项重新出现。 setState错误包裹异步逻辑:onDismissed回调中,将async函数直接传入setState,这是错误用法,setState的回调不能是异步函数,会导致状态更新时机异常。omLoadData未处理空数据:当本地无存储数据时,prefs.getStringList("todo_list")返回null,直接使用data!会触发空指针异常。Dismissible的Key存在重复风险:使用todoList[index]作为Key,如果存在相同内容的待办项,会导致Key重复,引发列表渲染错误。
修复方案与代码实现
以下是修复后的完整代码:
import 'package:flutter/material.dart'; import 'package:shared_preferences/shared_preferences.dart'; class Home extends StatefulWidget { const Home({key}) : super(key: key); @override State<Home> createState() => _HomeState(); } class _HomeState extends State<Home> { final myController = TextEditingController(); bool submit = false; Color mainColor = const Color(0xFFEEEFF5); Color secColor = const Color(0xFF3A3A3A); Color tdBlue = const Color(0xFF5F52EE); String temp = ""; List<String> todoList = []; @override void initState() { super.initState(); myController.addListener(() { setState(() { submit = myController.text.isNotEmpty; }); }); loadData(); } void submitData() async { setState(() { todoList.add(temp); clearText(); }); SharedPreferences prefs = await SharedPreferences.getInstance(); await prefs.setStringList('todo_list', todoList); } void loadData() async { SharedPreferences prefs = await SharedPreferences.getInstance(); final data = prefs.getStringList("todo_list"); if (data != null) { setState(() { todoList.addAll(data); }); } } Future<void> deleteItem(int index) async { setState(() { todoList.removeAt(index); }); // 删除后同步更新本地存储 SharedPreferences prefs = await SharedPreferences.getInstance(); await prefs.setStringList('todo_list', todoList); } @override void dispose() { myController.dispose(); super.dispose(); } void clearText() { myController.clear(); } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: mainColor, appBar: AppBar( elevation: 0.0, backgroundColor: secColor, title: const Text( 'ToDo - List', style: TextStyle( fontSize: 26.5, fontWeight: FontWeight.bold, fontStyle: FontStyle.italic), ), ), body: Column( children: [ Container( margin: const EdgeInsets.only(top: 15.0, left: 13.0, right: 8.0), child: Row( children: [ Expanded( child: TextField( onChanged: (String value) { temp = value; }, controller: myController, decoration: InputDecoration( prefixIcon: const Icon(Icons.notes, color: Colors.orangeAccent), labelText: 'Замітка', hintText: 'Введіть замітку', filled: true, fillColor: Colors.white, border: const OutlineInputBorder(), contentPadding: const EdgeInsets.all(10.0), enabledBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(30.0), ), ), ), ), const SizedBox(width: 10.0), ElevatedButton( style: ElevatedButton.styleFrom(backgroundColor: tdBlue), onPressed: submit ? () => submitData() : null, child: const Text('+', style: TextStyle(fontSize: 35)), ), ], ), ), Expanded( child: Padding( padding: const EdgeInsets.only(top: 5.0), child: ListView.builder( itemCount: todoList.length, itemBuilder: (BuildContext context, int index) { return Dismissible( direction: DismissDirection.endToStart, background: const Card( color: Colors.red, child: Icon(Icons.delete_sweep, size: 30, color: Colors.white), ), // 使用唯一Key避免重复 key: Key('${todoList[index]}-$index'), onDismissed: (direction) { deleteItem(index); }, child: Card( margin: const EdgeInsets.only(top: 8.5, left: 25.0, right: 25.0), shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(25.0)), elevation: 0.0, child: ListTile( title: Text(todoList[index]), ), ), ); }, ), ), ), ], ), ); } }
关键修复点说明
- 新增
deleteItem方法:将删除逻辑与本地存储更新分离,确保删除后立即同步数据到SharedPreferences。 - 修正
loadData函数:增加空值判断,避免无存储数据时的空指针异常,同时用setState更新UI。 - 修改
Dismissible的Key:使用'${todoList[index]}-$index'作为唯一标识,避免重复Key导致的渲染问题。 - 移除
setState中的异步逻辑:将异步操作移到setState之外,保证状态更新和数据持久化的顺序正确。
内容的提问来源于stack exchange,提问作者Назар Марцинко
相关产品推荐
相关产品推荐

