Is it possible to to return value in Coroutine Scope
without run blocking?
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. Is it efficient to call Dispatchers.Main all the time?
CoroutineScope(Dispatchers.Main).launch { }
CodePudding user response:
You could just pass the value from a coroutine to liveData and then use an observer
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)
}
CodePudding user response:
It doesn't make sense to use runBlocking
in a suspend function. (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
:
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. 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. 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)
}
CodePudding user response:
Have you ever listened about a lambda?
It looks like 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)}
}
}