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

如何在Hilt ViewModel场景下为Room数据库预填充初始数据

解决方案

你只需要将回调逻辑剥离原有单例实现,直接在Hilt的数据库提供方法中注册回调即可,以下是完整实现步骤:

步骤1:修改PuzzleDatabase添加回调类

你可以直接在数据库类中定义回调,通过原生SQL执行预填充,避免Dao依赖导致的循环依赖问题:

@Database(entities = [Puzzle::class], version = 1, exportSchema = false)
abstract class PuzzleDatabase : RoomDatabase() {
    abstract fun getPuzzleDao() : PuzzleDao

    class PuzzleDatabaseCallback(
        private val scope: CoroutineScope
    ) : RoomDatabase.Callback() {
        override fun onCreate(db: SupportSQLiteDatabase) {
            super.onCreate(db)
            // 仅在数据库首次创建时执行预填充
            scope.launch(Dispatchers.IO) {
                // 替换为你的Puzzle实体对应的表字段与插入值
                db.execSQL("INSERT INTO Puzzle (id, column1, column2, column3) VALUES (0, 9, 5, 'TWO')")
            }
        }
    }
}

步骤2:修改AppModule实现回调注册

首先提供应用级协程Scope,再在数据库构造时添加回调即可:

@Module
@InstallIn(SingletonComponent::class)
object AppModule {

    // 提供应用生命周期的协程Scope,用于预填充异步操作
    @Singleton
    @Provides
    fun provideAppCoroutineScope(): CoroutineScope = CoroutineScope(SupervisorJob() + Dispatchers.IO)

    @Singleton
    @Provides
    fun providePuzzleDatabase(
        @ApplicationContext app: Context,
        scope: CoroutineScope
    ) = Room.databaseBuilder(
        app,
        PuzzleDatabase::class.java,
        "puzzle_database"
    )
    // 注册预填充回调
    .addCallback(PuzzleDatabase.PuzzleDatabaseCallback(scope))
    .build()

    @Singleton
    @Provides
    fun getDao(db: PuzzleDatabase) = db.getPuzzleDao()
}

可选:需要使用Dao执行预填充的实现

如果你不想写原生SQL,非要使用Dao插入,可以通过Hilt EntryPoint规避循环依赖,实现如下:

  1. 首先定义EntryPoint接口:
@EntryPoint
@InstallIn(SingletonComponent::class)
interface PuzzleDaoEntryPoint {
    fun puzzleDao(): PuzzleDao
}
  1. 修改回调类,传入Context并通过EntryPoint获取Dao:
class PuzzleDatabaseCallback(
    private val context: Context,
    private val scope: CoroutineScope
) : RoomDatabase.Callback() {
    override fun onCreate(db: SupportSQLiteDatabase) {
        super.onCreate(db)
        scope.launch(Dispatchers.IO) {
            val dao = EntryPoints.get(
                context.applicationContext,
                PuzzleDaoEntryPoint::class.java
            ).puzzleDao()
            dao.insert(Puzzle(0, 9L, 5L, Puzzles.TWO))
        }
    }
}
  1. 注册回调时传入Context即可:
.addCallback(PuzzleDatabase.PuzzleDatabaseCallback(app, scope))

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.08 03:06:02