[英]How to return value in coroutine scope?
Is it possible to to return value in Coroutine Scope
without run blocking?是否可以在没有运行阻塞的情况下在
Coroutine Scope
中返回值? For now my code in repository looks like this:现在我在存储库中的代码如下所示:
suspend fun getWorkItem(workItemId: Int): WorkItemRoom? {
runBlocking {
return@runBlocking
CoroutineScope(Dispatchers.Main).launch {
getWorkItemByIdUseCase.build(workItemId)
}
}
return null
}
this is my useCase这是我的用例
class GetWorkItemByIdUseCase(private val workItemDao: WorkItemDao) :
BaseUseCase<Int, WorkItemRoom>() {
override suspend fun create(id: Int): WorkItemRoom {
return workItemDao.getWorkItemById(id)
}
}
baseUseCase基本用例
abstract class BaseUseCase<P, R> {
protected abstract suspend fun create(params: P): R
open suspend fun build(params: P): R = create(params)
}
Dao道
@Dao
abstract class WorkItemDao {
@Query("SELECT * FROM workitem WHERE id=:id")
abstract suspend fun getWorkItemById(id: Int): WorkItemRoom
}
... but certainly I know it is not a proper solution. ...但我当然知道这不是一个合适的解决方案。 How would you achieve this?
您将如何实现这一目标? In
viewmodels' or fragments I can directly use
lifecycleScope`, but what in other cases, where the must is to call useCase directly from method below.在
viewmodels' or fragments I can directly use
生命周期范围,但在其他情况下,必须直接从下面的方法调用 useCase。 Is it efficient to call Dispatchers.Main all the time?一直调用 Dispatchers.Main 是否有效?
CoroutineScope(Dispatchers.Main).launch { }
It doesn't make sense to use runBlocking
in a suspend function.在挂起函数中使用
runBlocking
没有意义。 (It hardly ever makes sense to use it at all, except as a bridge between coroutines and non-coroutine code in a project that is partially converted to using coroutines but still needs to support legacy code or libraries.) (使用它几乎没有任何意义,除非在项目中作为协程和非协程代码之间的桥梁,该项目部分转换为使用协程但仍需要支持遗留代码或库。)
You should just call the function you need.你应该只调用你需要的函数。
suspend fun getWorkItem(workItemId: Int): WorkItemRoom? { //may not need nullable return value
return getWorkItemByIdUseCase.build(workItemId)
}
If you need to specify a dispatcher, use withContext
:如果需要指定调度程序,请使用
withContext
:
suspend fun getWorkItem(workItemId: Int): WorkItemRoom? = withContext(Dispatchers.Main) {
getWorkItemByIdUseCase.build(workItemId)
}
However, if build
is a suspend function, there's no need to specify a Dispatcher when calling it.但是,如果
build
是一个挂起函数,则在调用它时无需指定 Dispatcher。 Suspend functions are responsible for internally calling their functions on appropriate threads/dispatchers.挂起函数负责在适当的线程/调度程序上内部调用它们的函数。
If you need a coroutine scope inside a coroutine or suspend function, use the lowercase coroutineScope
function, which creates a scope that will be automatically cancelled if the coroutine is cancelled.如果您需要在协程或挂起函数中使用协程作用域,请使用小写的
coroutineScope
函数,该函数会创建一个作用域,如果协程被取消,该作用域将自动取消。 This example doesn't make much sense, because normally you don't need a new scope unless you are running parallel jobs inside it:这个例子没有多大意义,因为通常你不需要一个新的范围,除非你在其中运行并行作业:
suspend fun getWorkItem(workItemId: Int): WorkItemRoom? = coroutineScope(Dispatchers.Main) {
getWorkItemByIdUseCase.build(workItemId)
}
You could just pass the value from a coroutine to liveData and then use an observer您可以将协程中的值传递给 liveData,然后使用观察者
private val observableMutableLiveData = MutableLiveData<Type>()
val observableLiveData: LiveData<Type> = observableMutableLiveData
and later in a coroutine:后来在协程中:
CoroutineScope(Dispatchers.Main).launch {
observableMutableLiveData.postValue(value)
}
and then in an activity:然后在一个活动中:
viewModel.observableLiveData.observe(this) { Type ->
Log.i("result", Type)
}
Have you ever listened about a lambda ?你听过lambda吗?
It looks like call: (MyResult) -> Unit
看起来像
call: (MyResult) -> Unit
I use it from time to time like我不时使用它
fun someToDo(call: (MyResult) -> Unit) {
scope.launch(Dispatchers.IO) {
val result = getFromSomeWere()
launch(Dispatchers.Main){call(result)}
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.