将Provider与SharedPreferences集成实现任务数据持久化存取
问题分析与解决方案
核心问题点
getData()异步操作未触发Provider状态更新,且空值处理逻辑错误build方法中重复调用getData()导致不必要的异步请求与UI异常- 序列化/反序列化逻辑存在冗余,且存在潜在解析报错风险
修复步骤
1. 修正getData()函数
- 处理
SharedPreferences返回null的场景,避免将"null"字符串传入解析函数 - 异步操作完成后调用
notifyListeners()通知UI更新
Future<void> getData() async { final prefs = await SharedPreferences.getInstance(); final String? taskString = prefs.getString('task_data'); if (taskString == null) { _tasks = []; notifyListeners(); return; } List<Task> tasksData = Task.decode(taskString); _tasks = tasksData; notifyListeners(); }
2. 优化序列化/反序列化逻辑
- 移除重复的
jsonDecode调用,减少不必要的性能开销
static String encode(List<Task> tasks) { return jsonEncode( tasks.map<Map<String, dynamic>>((task) => Task.toMap(task)).toList(), ); } static List<Task> decode(String tasks) { final data = jsonDecode(tasks) as List<dynamic>?; return data?.map<Task>((task) => Task.fromJson(task)).toList() ?? []; }
3. 调整getData()的调用时机
- 不要在
build方法中调用getData(),改为在TaskData初始化时加载数据,避免UI重复重建时反复读取本地存储
class TaskData extends ChangeNotifier { List<Task> _tasks = []; TaskData() { _loadData(); } Future<void> _loadData() async { await getData(); } // 其他方法(saveData、updateTask等)... }
4. 优化任务修改与排序逻辑
- 将排序逻辑移到任务修改方法内,避免每次ListView构建都重复排序
- 确保任务修改后触发状态更新
void upDateTask(Task task) { task.toggleDone(); _tasks.sort((a, b) => a.isDone.compareTo(b.isDone)); notifyListeners(); } void removeTask(Task task) { _tasks.remove(task); notifyListeners(); }
5. 修正ListView的Build逻辑
- 移除
build方法中的taskData.getData()和taskData.sortTaskList()调用
Widget build(BuildContext context) { return Consumer<TaskData>( builder: (context, taskData, child) { return ListView.builder( itemCount: taskData.taskCount, itemBuilder: (context, index) { final task = taskData.tasks[index]; return TaskTile( taskTitle: task.name, isChecked: task.isDone, checkboxCallBack: (checkBoxState) { taskData.upDateTask(task); taskData.saveData(); }, longPressCallBack: () { taskData.removeTask(task); taskData.saveData(); }, ); }, ); }, ); }
额外验证项
确认Task类的toMap和fromJson方法能正确转换所有字段,示例:
class Task { String name; bool isDone; Task({required this.name, this.isDone = false}); Map<String, dynamic> toMap() { return { 'name': name, 'isDone': isDone, }; } factory Task.fromJson(Map<String, dynamic> json) { return Task( name: json['name'], isDone: json['isDone'] ?? false, ); } void toggleDone() { isDone = !isDone; } }
内容的提问来源于stack exchange,提问作者Sai Gruheeth
相关产品推荐
相关产品推荐

