Flutter应用重启后SQFlite数据无法自动加载,求原生优化方案
问题分析与解决方案
问题根源
你遇到的核心问题是异步操作顺序错误:在initState中调用_notesService.open()后立即执行_updateNotesInitial(),但open()是异步方法,此时数据库还未完成初始化,调用getNotes()会因为数据库未就绪而失败,导致StreamController没有数据流入,重启后自然无法显示笔记。而点击浮动按钮时数据库已经完成初始化,所以能正常获取并显示数据。
优化方案(无需重复打开数据库)
1. 修正数据库初始化的异步顺序
在initState中通过open()的then回调触发初始数据加载,确保数据库完全打开后再执行数据查询:
@override void initState() { _text = TextEditingController(); _notesService = NotesService(); _streamController = StreamController<List<Note>>(); // 等待数据库初始化完成后加载初始数据 _notesService.open().then((_) { _updateNotesInitial(); }).catchError((err) { debugPrint('数据库初始化失败: $err'); // 发送空列表避免加载指示器一直显示 _streamController.sink.add([]); }); super.initState(); }
2. 完善NotesService的初始化逻辑
确保open()方法中等待表创建完成,避免后续查询时表未就绪:
Future<void> open() async { final db = _db; if (db != null) { throw NotesDatabase_Exception(); } else { final Directory docsPath = await getApplicationDocumentsDirectory(); final String path = join(docsPath.path, databaseName); final db = await openDatabase(path); _db = db; await db.execute(create); // 添加await,确保表创建完成 } }
3. 统一数据库异常处理
修改getNotes()方法,复用已有的_getDatabaseOrThrow getter,避免重复判断数据库状态:
Future<List<Note>> getNotes() async { final db = _getDatabaseOrThrow; // 统一用getter处理未初始化的情况 final notes = await db.query('NOTETABLE'); final results = notes.map((row) => Note.fromMap(map: row)).toList(); return results; }
4. 给初始数据加载添加错误处理
避免因异常导致Stream一直没有数据:
Future<void> _updateNotesInitial() async { try { final notes = await _notesService.getNotes(); _streamController.sink.add(notes); } catch (e) { debugPrint('加载初始笔记失败: $e'); _streamController.sink.add([]); } }
效果验证
修改后,重启应用时会等待数据库初始化完成,再加载并发送笔记数据到Stream,StreamBuilder就能正常接收数据并显示笔记,无需重复打开数据库。
内容的提问来源于stack exchange,提问作者miguel
相关产品推荐
相关产品推荐

