Flutter待办清单应用数据丢失:如何实现持久化存储?
Flutter 待办清单数据持久化解决方案
你的问题核心是未实现本地数据持久化,以下是几种实用的实现方案,可根据你的需求选择:
方案一:SharedPreferences(适合少量简单待办数据)
这是Flutter官方推荐的轻量级存储方案,适合存储字符串、布尔值、数字等简单类型数据,适配待办项不多的场景。
实现步骤:
- 添加依赖到
pubspec.yaml:
dependencies: shared_preferences: ^2.2.2
- 封装存储工具类:
import 'package:shared_preferences/shared_preferences.dart'; class TodoStorage { // 保存待办列表 static Future<void> saveTodos(List<String> todos) async { final prefs = await SharedPreferences.getInstance(); await prefs.setStringList('todos', todos); } // 读取待办列表 static Future<List<String>> getTodos() async { final prefs = await SharedPreferences.getInstance(); return prefs.getStringList('todos') ?? []; } }
- 在待办页面中使用:
- 初始化时读取数据:
List<String> _todos = []; @override void initState() { super.initState(); _loadTodos(); } Future<void> _loadTodos() async { _todos = await TodoStorage.getTodos(); setState(() {}); }
- 添加/删除待办后立即保存:
void _addTodo(String todo) { setState(() { _todos.add(todo); }); TodoStorage.saveTodos(_todos); } void _deleteTodo(int index) { setState(() { _todos.removeAt(index); }); TodoStorage.saveTodos(_todos); }
方案二:Hive(轻量级NoSQL,适合结构化数据)
如果你的待办项需要包含更多属性(比如截止时间、完成状态),Hive是更优选择,它性能高且无需SQL知识。
实现步骤:
- 添加依赖:
dependencies: hive: ^2.2.3 hive_flutter: ^1.1.0 dev_dependencies: hive_generator: ^1.1.5 build_runner: ^2.4.4
- 创建待办模型并生成适配器:
- 新建
todo.dart模型文件:
import 'package:hive/hive.dart'; part 'todo.g.dart'; @HiveType(typeId: 0) class Todo extends HiveObject { @HiveField(0) String title; @HiveField(1) bool isCompleted; @HiveField(2) DateTime? deadline; Todo({required this.title, this.isCompleted = false, this.deadline}); }
- 运行命令生成适配器代码:
flutter packages pub run build_runner build
- 在
main.dart初始化Hive:
import 'package:hive_flutter/hive_flutter.dart'; import 'todo.dart'; void main() async { await Hive.initFlutter(); Hive.registerAdapter(TodoAdapter()); await Hive.openBox<Todo>('todos'); runApp(const MyApp()); }
- 操作数据:
final todoBox = Hive.box<Todo>('todos'); // 添加待办 void _addTodo(Todo todo) { todoBox.add(todo); } // 获取所有待办 List<Todo> _todos = todoBox.values.toList(); // 删除待办 void _deleteTodo(int index) { todoBox.deleteAt(index); } // 更新待办状态 void _toggleTodo(int index) { final todo = todoBox.getAt(index)!; todo.isCompleted = !todo.isCompleted; todo.save(); }
方案三:SQLite(适合复杂、大量数据)
如果应用需要复杂查询、关联数据,SQLite是标准选择,可通过sqflite库实现。
实现步骤:
- 添加依赖:
dependencies: sqflite: ^2.3.0 path_provider: ^2.1.1
- 编写数据库操作类:
import 'package:sqflite/sqflite.dart'; import 'package:path/path.dart'; class TodoDatabase { static final TodoDatabase instance = TodoDatabase._init(); static Database? _database; TodoDatabase._init(); Future<Database> get database async { if (_database != null) return _database!; _database = await _initDB('todos.db'); return _database!; } Future<Database> _initDB(String filePath) async { final dbPath = await getDatabasesPath(); final path = join(dbPath, filePath); return await openDatabase(path, version: 1, onCreate: _createDB); } Future<void> _createDB(Database db, int version) async { await db.execute(''' CREATE TABLE todos ( id INTEGER PRIMARY KEY AUTOINCREMENT, title TEXT NOT NULL, is_completed INTEGER NOT NULL DEFAULT 0, deadline TEXT ) '''); } // 添加待办 Future<int> addTodo(Map<String, dynamic> todo) async { final db = await instance.database; return await db.insert('todos', todo); } // 获取所有待办 Future<List<Map<String, dynamic>>> getTodos() async { final db = await instance.database; return await db.query('todos'); } // 更新待办状态 Future<int> toggleTodo(int id, bool isCompleted) async { final db = await instance.database; return await db.update( 'todos', {'is_completed': isCompleted ? 1 : 0}, where: 'id = ?', whereArgs: [id], ); } // 删除待办 Future<int> deleteTodo(int id) async { final db = await instance.database; return await db.delete( 'todos', where: 'id = ?', whereArgs: [id], ); } }
- 在页面中使用:
final db = TodoDatabase.instance; // 初始化读取数据 List<Map<String, dynamic>> _todos = []; @override void initState() { super.initState(); _loadTodos(); } Future<void> _loadTodos() async { _todos = await db.getTodos(); setState(() {}); } // 添加待办 void _addTodo(String title) async { await db.addTodo({ 'title': title, 'is_completed': 0, 'deadline': DateTime.now().toIso8601String(), }); _loadTodos(); }
内容的提问来源于stack exchange,提问作者Cayden Atti
相关产品推荐
相关产品推荐

