Flutter集成Sembast搭配Cubit开发时getDatabaseFactory问题咨询
问题1:解决getDatabaseFactory找不到的问题
getDatabaseFactory不是sembast官方提供的公开方法,是原示例作者自行封装的跨平台适配工具函数,所以你直接拷贝代码片段会找不到该方法,不是缺少公开依赖的问题。
解决方法如下:
- 先确认你已经引入了对应平台的sembast依赖:
- 通用依赖:
sembast: ^3.6.0 - Web端额外依赖:
sembast_web: ^2.4.0 - 移动端/桌面端额外依赖:
sqflite_common_ffi: ^2.3.0
- 通用依赖:
- 你可以直接替换原有的
getDatabaseFactory调用,手动做平台适配即可,示例代码:
import 'package:sembast/sembast.dart'; import 'package:sembast_web/sembast_web.dart'; import 'package:sqflite_common_ffi/sqflite_ffi.dart'; import 'package:flutter/foundation.dart'; DatabaseFactory getDatabaseFactory({required String packageName}) { if (kIsWeb) { return databaseFactoryWeb; } else { if (Platform.isWindows || Platform.isLinux || Platform.isMacOS) { sqfliteFfiInit(); } return databaseFactoryFfi; } }
你可以把上面这个工具函数加到自己的项目里,就能和原示例逻辑对齐。
问题2:note_provider简化方案
原示例的note_provider做了大量接口抽象、异常兼容、全操作封装,适合大型项目复用,轻量项目可以直接简化为单例的数据库操作类,示例实现:
class NoteDbHelper { static final NoteDbHelper _instance = NoteDbHelper._internal(); factory NoteDbHelper() => _instance; NoteDbHelper._internal(); late final Database _db; final _noteStore = intMapStoreFactory.store('notes'); Future<void> init(DatabaseFactory dbFactory) async { _db = await dbFactory.openDatabase('notes.db'); } Stream<List<Note>> get onNotes => _noteStore.query(finder: Finder(sortOrders: [SortOrder('createTime', false)])).onSnapshots(_db).map((snapshots) => snapshots.map((s) => Note.fromJson(s.value)).toList()); Future<void> addNote(Note note) async { await _noteStore.add(_db, note.toJson()); } Future<void> deleteNote(int id) async { await _noteStore.record(id).delete(_db); } }
只保留你需要的增删改查方法即可,不需要额外的接口层和状态封装。
问题3:适配Bloc架构的方案
你目前的监听onNotes Stream、收到事件时emit状态的方案是完全合理的,更优的实现是直接用Cubit提供的emit.forEach方法自动订阅流,不需要手动管理StreamSubscription的销毁,避免内存泄漏,示例实现:
class NoteCubit extends Cubit<NoteState> { NoteCubit() : super(NoteLoading()) { _subscribeNotes(); } final _dbHelper = NoteDbHelper(); Future<void> _subscribeNotes() async { await emit.forEach<List<Note>>( _dbHelper.onNotes, onData: (notes) => NoteLoaded(notes), onError: (e, st) => NoteError(e.toString()), ); } Future<void> addNote(Note note) async { await _dbHelper.addNote(note); } Future<void> deleteNote(int id) async { await _dbHelper.deleteNote(id); } }
这种实现方式不需要你手动调用listen、也不需要在Cubit关闭时手动取消订阅,bloc会自动处理流的生命周期,逻辑更简洁也更安全。
内容的提问来源于stack exchange,提问作者geoai777
相关产品推荐
相关产品推荐

