【问题标题】:Trying to prepopulate Room Database from a json using Hilt尝试使用 Hilt 从 json 预填充房间数据库
【发布时间】:2023-03-11 07:33:01
【问题描述】:

我有一个应用程序,我在其中使用 json 文件预填充我的房间数据库。这是我的数据库设置:

@Database(version = 2, entities = [(ClimbingRoute::class)], exportSchema = false)
abstract class ClimbingRoutesDatabase : RoomDatabase() {

    abstract fun climbingRouteDao(): ClimbingRouteDao

    private class ClimbingRouteDatabaseCallback(
        private val scope: CoroutineScope,
        private val resources: Resources
    ) : RoomDatabase.Callback() {

        override fun onCreate(db: SupportSQLiteDatabase) {
            super.onCreate(db)
            INSTANCE?.let { database ->
                //1
                scope.launch{
                    val climbingRouteDao = database.climbingRouteDao() // 2
                    prePopulateDatabase(climbingRouteDao) // 3
                }            }
        }
        private suspend fun prePopulateDatabase(climbingRouteDao: ClimbingRouteDao){
            // 1
            val jsonString = resources.openRawResource(R.raw.climbing_routes).bufferedReader().use {
                it.readText()
            }
            // 2
            val typeToken = object : TypeToken<List<ClimbingRoute>>() {}.type
            val boulderClimbingRoutes = Gson().fromJson<List<ClimbingRoute>>(jsonString, typeToken)
            // 3
            climbingRouteDao.insertAllClimbingRoutes(boulderClimbingRoutes)
        }
    }


    companion object {

        @Volatile
        private var INSTANCE: ClimbingRoutesDatabase? = null

        fun getDatabase(
            context: Context,
            coroutineScope: CoroutineScope, // 1
            resources: Resources // 2
        ): ClimbingRoutesDatabase {
            val tempInstance = INSTANCE
            if (tempInstance != null) {
                return tempInstance
            }

            synchronized(this) {
                val instance = Room.databaseBuilder(context.applicationContext,
                    ClimbingRoutesDatabase::class.java,
                    "climbing_routes_database")
                    .addCallback(ClimbingRouteDatabaseCallback(coroutineScope, resources))
                    .build()
                INSTANCE = instance
                return instance
            }
        }
    }
}

现在我正在学习使用 Hilt 的 codingwithflow 教程。我想使用他的模式将依赖注入添加到我的应用程序中。这是他的教程中codingwithflow的TaskDatabase和AppModule。

他的任务数据库

@Database(entities = [Task::class], version = 1)
abstract class TaskDatabase : RoomDatabase() {

    abstract fun taskDao(): TaskDao

    class Callback @Inject constructor(
        private val database: Provider<TaskDatabase>,
        @ApplicationScope private val applicationScope: CoroutineScope,
    ) : RoomDatabase.Callback() {

        override fun onCreate(db: SupportSQLiteDatabase) {
            super.onCreate(db)

            val dao = database.get().taskDao()

            applicationScope.launch {
                dao.insert(Task("Wash the dishes"))
                dao.insert(Task("Do the laundry"))
                dao.insert(Task("Buy groceries", important = true))
                dao.insert(Task("Prepare food", completed = true))
                dao.insert(Task("Call mom"))
                dao.insert(Task("Visit grandma", completed = true))
                dao.insert(Task("Repair my bike"))
                dao.insert(Task("Call Elon Musk"))
            }
        }
    }
}

他的 AppModule:

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

    @Provides
    @Singleton
    fun provideDatabase(
        app: Application,
        callback: TaskDatabase.Callback
    ) = Room.databaseBuilder(app, TaskDatabase::class.java, "task_database")
        .fallbackToDestructiveMigration()
        .addCallback(callback)
        .build()

    @Provides
    fun provideTaskDao(db: TaskDatabase) = db.taskDao()

    @ApplicationScope
    @Provides
    @Singleton
    fun provideApplicationScope() = CoroutineScope(SupervisorJob())
}

@Retention(AnnotationRetention.RUNTIME)
@Qualifier
annotation class ApplicationScope

我已尝试将这种方法用于我的应用程序,但无法使用我的带有依赖注入的 json 成功预填充数据库。应用程序正在加载,没有崩溃,但我一直得到一个空数据库。

我对 di 的理解还不够,无法修改 appmodule 以使其工作。这是我现在的数据库设置、appmodule 和 dao。 (不工作):

我的攀登路线数据库:

@Database(entities = [(ClimbingRoute::class)], version = 1, exportSchema = false)
abstract class ClimbingRouteDatabase : RoomDatabase() {

    abstract fun climbingRouteDao(): ClimbingRouteDao

    class Callback @Inject constructor(
        private val database: Provider<ClimbingRouteDatabase>,
        @ApplicationScope private val applicationScope: CoroutineScope,
        private val resources: Resources
    ) : RoomDatabase.Callback() {

        override fun onCreate(db: SupportSQLiteDatabase) {
            super.onCreate(db)

            val climbingRouteDao = database.get().climbingRouteDao()

                applicationScope.launch{
                    prePopulateDatabase(climbingRouteDao)
                }
        }

        private suspend fun prePopulateDatabase(climbingRouteDao: ClimbingRouteDao){
            
            val jsonString = resources.openRawResource(R.raw.climbing_routes).bufferedReader().use {
                it.readText()
            }
            
            val typeToken = object : TypeToken<List<ClimbingRoute>>() {}.type
            val boulderClimbingRoutes = Gson().fromJson<List<ClimbingRoute>>(jsonString, typeToken)
            
            climbingRouteDao.insert(boulderClimbingRoutes)
        }
    }
}

我的应用模块:

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

    @Provides
    @Singleton
    fun provideDatabase(
        app: Application,
        callback: ClimbingRouteDatabase.Callback
    ) = Room.databaseBuilder(
        app,
        ClimbingRouteDatabase::class.java,
        "climbing_route_database")
        .fallbackToDestructiveMigration()
        .addCallback(callback)
        .build()

    @Provides
    fun provideClimbingRouteDao(db: ClimbingRouteDatabase) = db.climbingRouteDao()

    @Provides
    @Singleton
    fun resourcesProvider(@ApplicationContext context: Context): Resources = context.resources

    @ApplicationScope
    @Provides
    @Singleton
    fun provideApplicationScope() = CoroutineScope(SupervisorJob())
}

@Retention(AnnotationRetention.RUNTIME)
@Qualifier
annotation class ApplicationScope

攀登路线道

@Dao
interface ClimbingRouteDao {

    @Insert(onConflict = OnConflictStrategy.IGNORE)
    suspend fun insert(climbingRoutes: List<ClimbingRoute>)

    @Query("SELECT * FROM climbing_route_table")
    fun getClimbingRoutes(): Flow<List<ClimbingRoute>>

    @Update
    suspend fun update(climbingRoutes: ClimbingRoute)

    @Delete
    suspend fun delete(climbingRoutes: ClimbingRoute)
}

任何帮助将不胜感激。谢谢。

【问题讨论】:

    标签: android dependency-injection android-room dagger-hilt android-database


    【解决方案1】:

    好的,所以我通过......解决了这个问题

    在从 ANDROID STUDIO 再次运行之前从我的设备中卸载该应用程序!

    天哪,我猜是生活和学习。到目前为止,上面的代码似乎运行良好。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-10-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-10-22
      • 2021-12-28
      • 1970-01-01
      相关资源
      最近更新 更多