如何为Flutter待办事项列表正确实现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,提问作者Назар Марцинко
相关产品推荐
相关产品推荐

