You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

KMP中Android与iOS端用Room访问预填充SQLite数据库方案问询

在KMP中为Android和iOS端通过Room使用预填充SQLite数据库的方案

前提配置:共享模块引入Room Multiplatform

首先在KMP共享模块的build.gradle.kts中配置Room Multiplatform依赖,确保跨平台支持:

plugins {
    kotlin("multiplatform")
    id("com.android.library")
    id("androidx.room")
}

kotlin {
    androidTarget()
    iosX64()
    iosArm64()
    iosSimulatorArm64()

    sourceSets {
        val commonMain by getting {
            dependencies {
                implementation("androidx.room:room-runtime:2.6.1")
                implementation("androidx.room:room-ktx:2.6.1")
                implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3")
            }
        }
        val androidMain by getting {
            dependencies {
                implementation("androidx.core:core-ktx:1.12.0")
            }
        }
        val iosMain by getting
    }
}

room {
    schemaDirectory("$projectDir/schemas")
}

在共享模块中定义通用的实体、DAO和数据库基类:

// 实体类
@Entity(tableName = "sample_table")
data class SampleEntity(
    @PrimaryKey val id: Int,
    val name: String
)

// DAO接口
@Dao
interface SampleDao {
    @Query("SELECT * FROM sample_table")
    suspend fun getAll(): List<SampleEntity>
}

// 数据库核心类,两端分别实现预填充逻辑
@Database(entities = [SampleEntity::class], version = 1, exportSchema = true)
abstract class AppDatabase : RoomDatabase() {
    abstract fun sampleDao(): SampleDao

    companion object {
        fun buildDatabase(context: Any): AppDatabase = when (context) {
            is Context -> buildAndroidDb(context)
            is NSFileManager -> buildIosDb(context)
            else -> throw IllegalArgumentException("Unsupported context type")
        }

        // Android端预填充实现
        private fun buildAndroidDb(context: Context): AppDatabase =
            Room.databaseBuilder(context, AppDatabase::class.java, "mysqlite_sample.db")
                .createFromAsset("mysqlite_sample.db")
                .build()

        // iOS端预填充实现(下文详细说明)
        private fun buildIosDb(fileManager: NSFileManager): AppDatabase {
            // 逻辑见下文
        }
    }
}

Android端实现

  1. 将预填充的mysqlite_sample.db放入Android模块的src/main/assets目录。
  2. 在Android应用中直接传入Context获取数据库实例:
val db = AppDatabase.buildDatabase(applicationContext)
// 调用DAO方法示例
lifecycleScope.launch {
    val data = db.sampleDao().getAll()
    // 处理数据
}

Room会自动将assets目录中的数据库复制到应用的私有数据库目录,无需额外操作。


iOS端实现

iOS没有Room原生的createFromAsset方法,需要手动完成数据库复制逻辑:

1. 添加数据库到iOS资源

将mysqlite_sample.db拖入iOS模块的Resources目录,在Xcode中勾选"Copy items if needed",并确保该文件被加入目标应用的Build Phases > Copy Bundle Resources列表。

2. 实现数据库复制与初始化

完善共享模块中buildIosDb方法的逻辑,将Bundle中的数据库复制到应用的Documents目录(Room在iOS上默认使用该目录存储数据库):

private fun buildIosDb(fileManager: NSFileManager): AppDatabase {
    val dbName = "mysqlite_sample.db"
    // 获取Documents目录路径
    val documentsDir = fileManager.URLsForDirectory(
        NSDocumentDirectory,
        NSUserDomainMask
    ).first() as NSURL
    val targetDbPath = documentsDir.path + "/$dbName"

    // 仅当目标路径无数据库时执行复制
    if (!fileManager.fileExistsAtPath(targetDbPath)) {
        val bundleDbPath = NSBundle.mainBundle().pathForResource(dbName, null)
            ?: throw IllegalStateException("Pre-populated database not found in iOS bundle")
        
        fileManager.copyItemAtPath(bundleDbPath, targetDbPath, null)
    }

    // 初始化Room数据库
    return Room.databaseBuilder<AppDatabase>(
        name = dbName,
        factory = { AppDatabase::class.instantiateImpl() }
    ).build()
}

3. iOS端调用示例

在Swift代码中传入FileManager实例获取数据库:

let db = AppDatabase.buildDatabase(context: FileManager.default)
Task {
    do {
        let samples = try await db.sampleDao().getAll()
        // 处理数据
    } catch {
        print("Error fetching data: \(error)")
    }
}

关键注意事项

  • 确保预填充数据库的版本号与共享模块@Database注解中的version完全一致,否则Room会触发迁移逻辑导致预填充数据失效。
  • iOS端需处理文件复制的异常情况,避免因资源缺失导致应用崩溃。
  • 测试时可通过Xcode查看应用包内容,确认mysqlite_sample.db已被正确打包。

内容的提问来源于stack exchange,提问作者Aristotele Songhori

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 04:57:16