如何使用 android room (Kotlin) 返回新插入的项目(行)id?

Nic*_*lde 2 android kotlin android-room

我正在对许多类似的主题使用类似的解决方案,但它仍然不想工作,并且无法弄清楚为什么:

我的实体

@Entity(tableName = "single_item")
data class SingleItem (
    @PrimaryKey(autoGenerate = true)
    val id: Long? = 0L,
    val name: String,
    val icon: String,
    val price: Int)
Run Code Online (Sandbox Code Playgroud)

DAO

@Insert
    suspend fun insertItem(item: SingleItem): Long
Run Code Online (Sandbox Code Playgroud)

回购协议

suspend fun insertItem(item: SingleItem): Long {
        return myDao.insertItem(item)
    }
Run Code Online (Sandbox Code Playgroud)

视图模型

var insertedId = 0L
fun insertItem(item: SingleItem) = viewModelScope.launch {
        insertedId = myRepository.insertItem(item)
    }
Run Code Online (Sandbox Code Playgroud)

最后,从 Fragment 调用

val newItem = SingleItem(null, "name","icon_name", 9999)
viewModel.insertItem(newItem)
Log.i("INSERT_ID", "Inserted ID is: ${viewModel.insertedId}")
Run Code Online (Sandbox Code Playgroud)

在我检查日志后,insertedId变量总是返回0。它不会改变。可能出了什么问题?

Fra*_*esc 5

viewmodel 中的insert方法正在启动一个新的协程,它在执行插入之前返回,因此您得到的初始值是 0。如果您等待作业完成,您将获得正确的 id。

像这样更改它以查看正确的值:

var insertedId = 0L
fun insertItem(item: SingleItem) = viewModelScope.launch {
    insertedId = myRepository.insertItem(item)
    Log.i("INSERT_ID", "Inserted ID is: $insertedId")
}
Run Code Online (Sandbox Code Playgroud)

如果您想在片段中获取此值,则必须等待作业完成。最好的方法是让你的视图模型insert方法成为一个suspend函数,而不是一劳永逸。

fun insertItem(item: SingleItem) = 
    myRepository.insertItem(item)
Run Code Online (Sandbox Code Playgroud)

并在片段中

lifecycleScope.launch {
    val id = viewModel.insertItem(item)
    Log.i("INSERT_ID", "Inserted ID is: $id")
}
Run Code Online (Sandbox Code Playgroud)

但请注意,这是错误的架构,所有业务逻辑都应该位于视图模型中,而不是片段中。