【发布时间】:2020-03-22 04:38:56
【问题描述】:
我不知道如何使用 Room 和 MVVM 模式进行“简单”操作。 我正在使用 Retrofit 获取一些数据。 “正确”的响应会触发活动中的观察者,并且响应本身的一小部分使用 Room 库插入到数据库中,擦除所有先前存储的值并插入新的值。否则旧值将保留在 DB 上。 之后,我想检查数据库中的某个字段,但我无法强制此操作等到前一个完成。
型号
@Entity(tableName = "licence")
data class Licence(
@PrimaryKey(autoGenerate = true)
@ColumnInfo(name = "licence_id")
var licenceId: Int = 0,
@Ignore
var config: List<LicenceConfig>? = null,
.......
//all the others attributes )
@Entity(foreignKeys = [
ForeignKey(
entity = Licence::class,
parentColumns = ["licence_id"],
childColumns = ["licence_reference"],
onDelete = ForeignKey.CASCADE
)],tableName = "licence_configurations")
data class LicenceConfig(
@PrimaryKey(autoGenerate = true)
@ColumnInfo(name = "licence_config_id")
var licenceConfigId: Int,
@ColumnInfo(name="licence_reference")
var licenceReference: Int,
活动中的观察者
loginViewModel.apiResponse.observe(this, Observer { response ->
response?.let {
loginViewModel.insertLicences(response.licence)
}
//here I need to wait for the insertion to end
loginViewModel.methodToCheckForTheFieldOnDatabase()
})
视图模型
fun insertLicences(licences: List<Licence>) = viewModelScope.launch {
roomRepository.deleteAllLicences()
licences.forEach { licence ->
roomRepository.insertLicence(licence).also { insertedLicenceId ->
licence.config?.forEach { licenceConfiguration ->
roomRepository.insertLicenceConfiguration(
licenceConfiguration.apply { licenceReference = insertedLicenceId.toInt() }
)
}
}
}
}
房间存储库
class RoomRepository(private val roomDao: RoomDao) {
val allLicences: LiveData<List<Licence>> = roomDao.getAllLicences()
suspend fun insertLicence(licence: Licence): Long {
return roomDao.insertLicence(licence)
}
suspend fun insertLicenceConfiguration(licenceConfiguration: LicenceConfig){
return roomDao.insertLicenceConfiguration(LicenceConfig)
}
}
房间道
@Dao
interface RoomDao {
@Query("select * from licence")
fun getAllLicences(): LiveData<List<Licence>>
@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insertLicence(licence: Licence): Long
@Insert
suspend fun insertLicenceConfiguration(licence: LicenceConfig)
@Query("DELETE FROM licence")
suspend fun deleteAllLicences()
}
将观察者设置为“allLicences”LiveData 或直接在 DB 上的该字段上不是一个选项,因为操作将在活动创建后立即执行,我必须等到 API 响应才能执行它们。
在另一个没有 Room 的项目中,我使用 async{} 和 .await() 在使用协程时执行顺序操作,但我无法真正让它在这里工作。当我在插入方法之后暂停调试器时,“allLicences”的值始终为空,但在恢复和导出数据库后,数据被正确插入。我还尝试在 ViewModel 方法之后添加 .invokeOnCompletion{},但结果相同。
基本上我想等待这个方法结束来做另一个操作。
有什么建议吗?
编辑
我完全忘了报告模型!每个许可证都有一个配置列表。当我执行许可证插入时,我采用自动生成的 ID,将其应用于 licenceConfig,然后为每个 licenceConfig 对象(ViewModel 方法的嵌套 forEach 循环中的代码)执行插入。问题似乎是执行这个嵌套循环破坏了操作的“同步性”
【问题讨论】:
标签: android kotlin mvvm android-room kotlin-coroutines