如何在Flutter中配置使用预填充本地数据库的Dart ObjectBox
Flutter ObjectBox预填充数据库实现方案
需求可行性说明
你提到的需求完全可以实现:ObjectBox支持直接加载外部预生成的数据库文件,同时自带完善的Schema迁移能力,两者可以同时兼容不会产生冲突。
搭建步骤
- 提前准备预填充数据库文件:先编写临时测试代码将需要预置的全部数据插入ObjectBox,运行项目后从测试设备的应用私有目录中导出生成的
data.mdb数据库文件,将该文件放入Flutter项目的assets/databases/路径下,同时在pubspec.yaml中完成assets资源声明。 - 应用启动时初始化数据库:首次启动应用时,先判断应用私有目录下是否存在ObjectBox数据库文件,不存在则将assets中预置的预填充文件复制到对应目录,已存在则跳过复制,避免覆盖用户后续产生的业务数据。
- 兼容Schema迁移:后续版本如果需要调整表结构,正常按照ObjectBox的迁移规范添加
@Uid注解、编写对应的迁移逻辑即可,ObjectBox在打开数据库实例时会自动检测版本执行迁移,和初始预填充的数据库文件互不影响。
核心数据库管理类实现
import 'dart:io'; import 'dart:typed_data'; import 'package:flutter/services.dart'; import 'package:path_provider/path_provider.dart'; import '../objectbox.g.dart'; /// 数据库管理器,负责数据库初始化与配置管理 class DatabaseManager { static DatabaseManager? _instance; DatabaseManager._internal(); /// 单例构造方法 factory DatabaseManager() { if (_instance == null) { _instance = DatabaseManager._internal(); } return _instance!; } /// 数据库初始化入口: /// 1. 复制assets中的预填充数据库文件到应用目录 /// 2. 测试数据库实例可以正常打开 Future<void> init() async { await copyDatabaseFileFromAssets(); await testInstanceAndCloseIt(); } /// 将assets中打包的预填充数据库复制到应用私有目录 Future<void> copyDatabaseFileFromAssets() async { // 读取assets中的预填充数据库文件 ByteData data = await rootBundle.load("assets/databases/data.mdb"); List<int> bytes = data.buffer.asUint8List(data.offsetInBytes, data.lengthInBytes); // 构造数据库文件存放路径,不存在则创建对应目录 Directory documentsDirectory = await getApplicationDocumentsDirectory(); String path = "${documentsDirectory.path}/objectbox/data.mdb"; // 仅当目标路径不存在数据库文件时才执行复制,避免覆盖用户已有数据 if (!await File(path).exists()) { var objectBoxDirectory = Directory("${documentsDirectory.path}/objectbox/"); if (!await objectBoxDirectory.exists()) { objectBoxDirectory.create(); } // 将预填充数据写入目标文件 await File(path).writeAsBytes(bytes); } } /// 测试数据库可以正常打开,打开后立即关闭即可 Future<void> testInstanceAndCloseIt() async { await openStore().then((Store store) { store.close(); }); } }
使用方式
在应用启动阶段(比如main函数中runApp之前)执行初始化即可:
void main() async { WidgetsFlutterBinding.ensureInitialized(); // 初始化数据库 await DatabaseManager().init(); runApp(const MyApp()); }
内容的提问来源于stack exchange,提问作者Dev Loots
相关产品推荐
相关产品推荐

