如何通过Hilt为Room数据库添加Callback实现数据预填充
解决方案
问题根源
所有报错本质都是依赖循环:
- PersonDatabase实例构建需要传入PersonCallback
- PersonCallback需要注入PersonDao
- PersonDao的实例又依赖PersonDatabase实例
三者形成依赖闭环,Hilt无法完成自动注入,手动调用provideDatabase也会触发递归死循环。
可行实现方案(推荐)
步骤1:改造PersonCallback,通过Hilt EntryPoint打破循环
EntryPoint可以在非Hilt管理的类中获取依赖,我们利用Room Callback的onCreate是数据库构建完成后才触发的特性,在回调执行时再获取Dao实例,无需在Callback构造时传入依赖:
class PersonCallback( private val context: Context ) : RoomDatabase.Callback() { private val applicationScope = CoroutineScope(SupervisorJob() + Dispatchers.IO) // 定义EntryPoint,用于获取PersonDao实例 @EntryPoint @InstallIn(SingletonComponent::class) interface PersonDaoEntryPoint { fun personDao(): PersonDao } override fun onCreate(db: SupportSQLiteDatabase) { super.onCreate(db) applicationScope.launch { // 数据库创建完成后,从Hilt中获取Dao val entryPoint = EntryPointAccessors.fromApplication( context, PersonDaoEntryPoint::class.java ) val dao = entryPoint.personDao() populateDatabase(dao) } } private suspend fun populateDatabase(dao: PersonDao) { val person = Person("FirstName", "LastName", 20) dao.insertData(person) } }
步骤2:修改DatabaseModule,传入Callback实例
@Module @InstallIn(SingletonComponent::class) // 注意旧版ApplicationComponent已废弃,统一用SingletonComponent object DatabaseModule { @Singleton @Provides fun provideDatabase( @ApplicationContext context: Context ): PersonDatabase { return Room.databaseBuilder( context, PersonDatabase::class.java, "person_database" ) // 直接传入带context的Callback即可,无需依赖Dao .addCallback(PersonCallback(context)) .build() } @Singleton @Provides fun provideDao(database: PersonDatabase) = database.personDao() }
轻量替代方案(无Hilt依赖)
如果预填充数据量小,不需要用到Dao的封装方法,可以直接在Callback中通过原生SQL操作,完全避免依赖问题:
class PersonCallback : RoomDatabase.Callback() { private val applicationScope = CoroutineScope(SupervisorJob() + Dispatchers.IO) override fun onCreate(db: SupportSQLiteDatabase) { super.onCreate(db) applicationScope.launch { // 直接通过db参数执行插入SQL,无需依赖Dao db.execSQL("INSERT INTO person (first_name, last_name, age) VALUES ('FirstName', 'LastName', 20)") } } }
内容的提问来源于stack exchange,提问作者Karunesh Palekar
相关产品推荐
相关产品推荐

