【问题标题】:How to get ID of insert query in Room db with coroutines如何使用协程在 Room db 中获取插入查询的 ID
【发布时间】:2020-07-19 08:14:04
【问题描述】:

我想通过协程在 Roomdb 中成功插入数据时得到回调


MyDao.kt

@Dao
interface MyDao {

    @Insert(onConflict = OnConflictStrategy.REPLACE)
    suspend fun insert(obj: Task): Long
}


TaskViewModel.kt

class TaskViewModel(var context:Context) : ViewModel{
    private var appDao: AppDao

    init {
        val db = AppDatabase.getInstance(context)
        appDao = db.appDao()
    }

    fun insertTask(tast: Task) {
        GlobalScope.launch {
          val mID = appDao.insert(task)
        }
    }
}

如何从insertTask()方法返回mID

提前谢谢你

【问题讨论】:

    标签: android kotlin android-room coroutine


    【解决方案1】:

    使用withContext 包装调用并将函数标记为挂起

    suspend insertTask(task: Task) = withContext(Dispatchers.IO) { appDao.insertTask(task) }
    

    在你看来:

    fun saveTask(t: Task) = lifecycleScope.launch {
        val id = viewModel.insertTask(t)
        Toast.makeText(context, "Task $id has been inserted", Toast.LENGTH_SHORT).show()
    }
    

    您还可以返回一个LiveData,在完成后触发回调:

    fun insertTask(task: Task): LiveData<Long> {
        val liveData = MutableLiveData<Long>()
        viewModelScope.launch {
            liveData.value = dao.insertTask(task)
        }
        return liveData
    }
    

    进一步的建议

    不要在视图模型中保留对上下文的引用。如果您需要上下文,请使用 AndroidViewModelAndroidViewModel#getApplication()

    【讨论】:

    • 感谢您的回答。我接受并投票,但我不想每次都从视图中调用 write lifecycleScope.launch{},那该怎么办?
    • 从视图中我只想这样调用 val id = viewModel.insertTask(t) 那么我需要做什么? @一些随机的 IT 男孩
    • 操作val id = viewModel.insertTask(t) 我相信不调用launch 或类似方法是不可能执行的。要调用suspend fun,您必须在CoroutineScope 内或在另一个suspend fun 内。如果你严格地想避免写lifecycleScope.launch,你可以返回一个LiveData,并观察它以在协程完成它的工作时得到通知,就像我所说的那样。这样你就不会阻塞 Android 上的 MainThread。另一方面,如果想阻塞 MainThread,您可以调用 runBlocking {},但这违背了插入后台线程的全部目的
    • 问题在于 MainThread 和 GlobalScope 不共享执行上下文,因此您必须通过 TaskViewModel#insertTask 传递回调,使用可观察模式或从 Fragment 调用启动。所以你可以这样做:fun insertTask(task: Task, callback: (Long) -&gt; Unit) { GlobalScope.launch { val id = dao.insert(task) callback.invoke(id) } }
    • 另外,避免使用GlobalScope;使用 viewModelScope ktx 可确保在调用 ViewModel#onCleared 时取消协程,因此您不会泄漏任何协程
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-08-07
    • 2020-09-12
    • 2022-01-08
    • 2020-10-16
    • 1970-01-01
    • 2021-06-04
    • 1970-01-01
    相关资源
    最近更新 更多