我有一个相对较大的数据库,可能需要 1 到 2 分钟来初始化,是否可以在使用 sqldelight(kotlin 多平台)而不是在应用程序启动时初始化数据库时加载预填充的数据库?
3 回答
对不起,但我还不能添加任何评论,这会更合适......
虽然没有直接回答你的问题,但 1 到 2 分钟对于 sqlite 来说真的非常非常长。你在做什么?我首先要确保您正确使用交易。1-2 分钟的插入数据(可能)会导致一个巨大的 db 文件。
或者,我不得不使用预填充数据库的问题与 .sq 文件的大尺寸(每个表超过 30 MB 的 INSERT 文本)有关,并且 SqlDeLight 默默地中断了生成,没有显示错误消息。
在初始化 sqldelight 之前,您需要将 db 文件放在 android 上的 assets 和 iOS 上的 bundle 中,并将它们复制到各自的文件夹中。
必须从 android 和 ios 上的资源中加载 db 感觉需要做很多工作 + 这意味着共享项目不会是唯一初始化数据的地方。
Kotlin MultiPlatform 库Moko-resources解决了共享模块中数据库的单一来源问题。它适用于 KMM 的方式与适用于 Android 和 iOS 的方式相同。
不幸的是,图书馆的样本中几乎没有使用此功能。我在预期的类 DatabaseDriverFactory 中添加了第二个方法(getDriver)来打开准备好的数据库,并在平台上实现它。例如,对于 androidMain:
actual class DatabaseDriverFactory(private val context: Context) {
actual fun createDriver(schema: SqlDriver.Schema, fileName: String): SqlDriver {
return AndroidSqliteDriver(schema, context, fileName)
}
actual fun getDriver(schema: SqlDriver.Schema, fileName: String): SqlDriver {
val database: File = context.getDatabasePath(fileName)
if (!database.exists()) {
val inputStream = context.resources.openRawResource(MR.files.dbfile.rawResId)
val outputStream = FileOutputStream(database.absolutePath)
inputStream.use { input: InputStream ->
outputStream.use { output: FileOutputStream ->
input.copyTo(output)
}
}
}
return AndroidSqliteDriver(schema, context, fileName)
}
}
MR.files.fullDb 是库生成的类中的 FileResource,它与位于 commonMain 模块的 resources/MR/files 目录中的文件名相关联。它的属性 rawResId 表示平台端资源 ID。
是的,但这可能很棘手。不仅仅是“多平台”。在尝试初始化 sqldelight 之前,您需要将 db 复制到 db 文件夹。这可能意味着应用程序启动时主线程上的 i/o。
现在没有标准的方法可以做到这一点。在初始化 sqldelight 之前,您需要将 db 文件放在 android 上的 assets 和 iOS 上的 bundle 中,并将它们复制到各自的文件夹中。显然,您首先要检查数据库是否存在,或者通过某种方式知道这是您的第一个应用程序运行。
如果您计划发布具有较新数据库的更新,则需要管理版本,而不仅仅是检查数据库是否存在。
虽然没有直接回答你的问题,但 1 到 2 分钟对于 sqlite 来说真的非常非常长。你在做什么?我首先要确保您正确使用交易。1-2 分钟的插入数据(可能)会导致一个巨大的 db 文件。
您唯一需要的是使用驱动程序指定 DB 文件的路径。
假设您的数据库位于/mnt/my_best_app_dbs/super.db
. name
现在,在 Driver的属性中传递路径。像这样的东西:
val sqlDriver: SqlDriver = AndroidSqliteDriver(Schema, context, "/mnt/my_best_app_dbs/best.db")
请记住,您可能需要具有允许您读取给定存储类型的权限。