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

如何为Flutter待办事项列表正确实现SharedPreferences本地存储

待办事项本地存储(SharedPreferences实现方案)

1. 添加依赖

在pubspec.yaml中添加shared_preferences依赖:

dependencies:
  flutter:
    sdk: flutter
  shared_preferences: ^2.2.2 # 可替换为最新版本

执行flutter pub get完成依赖安装。

2. 定义待办实体类

创建todo.dart文件,实现Todo模型的序列化/反序列化:

class Todo {
  final String id;
  final String title;
  final bool isCompleted;

  Todo({
    required this.id,
    required this.title,
    this.isCompleted = false,
  });

  // 转JSON对象
  Map<String, dynamic> toJson() {
    return {
      'id': id,
      'title': title,
      'isCompleted': isCompleted,
    };
  }

  // 从JSON对象转Todo实例
  factory Todo.fromJson(Map<String, dynamic> json) {
    return Todo(
      id: json['id'],
      title: json['title'],
      isCompleted: json['isCompleted'],
    );
  }
}

3. 实现本地存储仓库

创建todo_repository.dart文件,封装SharedPreferences的所有操作:

import 'dart:convert';
import 'package:shared_preferences/shared_preferences.dart';
import 'todo.dart';

class TodoRepository {
  static const String _storageKey = 'saved_todos';

  // 获取所有待办
  Future<List<Todo>> getTodos() async {
    final prefs = await SharedPreferences.getInstance();
    final String? todosJsonStr = prefs.getString(_storageKey);
    
    if (todosJsonStr == null) return [];
    final List<dynamic> todosJsonList = jsonDecode(todosJsonStr);
    return todosJsonList.map((json) => Todo.fromJson(json)).toList();
  }

  // 添加新待办
  Future<void> addTodo(Todo todo) async {
    final prefs = await SharedPreferences.getInstance();
    final currentTodos = await getTodos();
    currentTodos.add(todo);
    
    final todosJsonStr = jsonEncode(currentTodos.map((t) => t.toJson()).toList());
    await prefs.setString(_storageKey, todosJsonStr);
  }

  // 更新待办(状态/内容)
  Future<void> updateTodo(Todo updatedTodo) async {
    final prefs = await SharedPreferences.getInstance();
    final currentTodos = await getTodos();
    final targetIndex = currentTodos.indexWhere((t) => t.id == updatedTodo.id);
    
    if (targetIndex != -1) {
      currentTodos[targetIndex] = updatedTodo;
      final todosJsonStr = jsonEncode(currentTodos.map((t) => t.toJson()).toList());
      await prefs.setString(_storageKey, todosJsonStr);
    }
  }

  // 删除待办
  Future<void> deleteTodo(String todoId) async {
    final prefs = await SharedPreferences.getInstance();
    final currentTodos = await getTodos();
    currentTodos.removeWhere((t) => t.id == todoId);
    
    final todosJsonStr = jsonEncode(currentTodos.map((t) => t.toJson()).toList());
    await prefs.setString(_storageKey, todosJsonStr);
  }
}

4. 在Widget中使用仓库

示例主页代码,集成仓库完成核心功能:

import 'package:flutter/material.dart';
import 'todo.dart';
import 'todo_repository.dart';
import 'dart:math';

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

  @override
  State<TodoHomePage> createState() => _TodoHomePageState();
}

class _TodoHomePageState extends State<TodoHomePage> {
  final TodoRepository _repo = TodoRepository();
  final TextEditingController _inputController = TextEditingController();
  List<Todo> _todos = [];

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

  // 加载本地待办数据
  Future<void> _loadTodos() async {
    final todos = await _repo.getTodos();
    setState(() => _todos = todos);
  }

  // 添加新待办
  Future<void> _addNewTodo() async {
    if (_inputController.text.trim().isEmpty) return;
    final newTodo = Todo(
      id: Random().nextInt(100000).toString(), // 临时ID生成方式,建议用uuid包替代
      title: _inputController.text.trim(),
    );
    await _repo.addTodo(newTodo);
    _inputController.clear();
    _loadTodos();
  }

  // 切换待办完成状态
  Future<void> _toggleTodoStatus(Todo todo) async {
    final updatedTodo = Todo(
      id: todo.id,
      title: todo.title,
      isCompleted: !todo.isCompleted,
    );
    await _repo.updateTodo(updatedTodo);
    _loadTodos();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('待办列表')),
      body: Column(
        children: [
          Padding(
            padding: const EdgeInsets.all(12),
            child: Row(
              children: [
                Expanded(
                  child: TextField(
                    controller: _inputController,
                    decoration: const InputDecoration(hintText: '输入待办内容'),
                  ),
                ),
                const SizedBox(width: 8),
                ElevatedButton(onPressed: _addNewTodo, child: const Text('添加')),
              ],
            ),
          ),
          Expanded(
            child: ListView.builder(
              itemCount: _todos.length,
              itemBuilder: (context, index) {
                final todo = _todos[index];
                return ListTile(
                  title: Text(
                    todo.title,
                    style: TextStyle(
                      decoration: todo.isCompleted ? TextDecoration.lineThrough : null,
                    ),
                  ),
                  leading: Checkbox(
                    value: todo.isCompleted,
                    onChanged: (_) => _toggleTodoStatus(todo),
                  ),
                  trailing: IconButton(
                    icon: const Icon(Icons.delete, color: Colors.red),
                    onPressed: () async {
                      await _repo.deleteTodo(todo.id);
                      _loadTodos();
                    },
                  ),
                );
              },
            ),
          ),
        ],
      ),
    );
  }
}

关键提示

  • 唯一ID:示例用随机数生成ID,生产环境推荐使用uuid包生成可靠唯一ID,需在pubspec.yaml添加uuid: ^3.0.7依赖。
  • 异步处理:所有SharedPreferences操作都是异步的,必须用await确保操作完成后再更新UI。
  • 序列化逻辑:SharedPreferences仅支持存储基础类型,因此必须将Todo对象转为JSON字符串存储,再从字符串解析回对象。

内容的提问来源于stack exchange,提问作者Назар Марцинко

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 16:45:21