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

将Provider与SharedPreferences集成实现任务数据持久化存取

问题分析与解决方案

核心问题点

  1. getData()异步操作未触发Provider状态更新,且空值处理逻辑错误
  2. build方法中重复调用getData()导致不必要的异步请求与UI异常
  3. 序列化/反序列化逻辑存在冗余,且存在潜在解析报错风险

修复步骤

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 16:58:58