我希望在使用协程向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
?谢谢您的提前预约。
val id = viewModel.insertTask(t)
。 要调用suspend fun
,您必须在CoroutineScope
内部或另一个suspend fun
内部。 如果您严格要避免编写lifecycleScope.launch
,则可以返回LiveData
并观察它以在协程完成其工作时收到通知,就像我所说的那样。 这样您就不会阻塞Android上的MainThread。 另一方面,如果要阻塞MainThread,则可以调用runBlocking {}
,但这将击败在后台线程中插入的整个目的。 - Some random IT boylifecycleScope.launch{}
,你可以编写以下 Kotlin 扩展函数来为你包装启动:fun Fragment.launch(coroutine: suspend CoroutineScope.() -> Unit) = lifecycleScope.launch(coroutine)
。这样你就可以在任何Fragment
中调用它,例如:fun doSomething(): = launch { /*你的协程代码放在这里*/}
。 - Some random IT boyTaskViewModel
中我使用了CoroutineScope
,但是当我想要从Fragment调用该方法时,我不想使用launch
或其他东西。我只想像这样调用val id = viewModel.insertTask(t)
。 - SanjayrajsinhTaskViewModel#insertTask
传递回调、使用可观察模式或从Fragment
调用launch。所以你可以这样做:fun insertTask(task: Task, callback: (Long) -> Unit) { GlobalScope.launch { val id = dao.insert(task) callback.invoke(id) } }
- Some random IT boyGlobalScope
;使用viewModelScope
ktx可确保协程在调用ViewModel#onCleared
时被取消,因此您不会泄漏任何协程。 - Some random IT boy