在我目前的项目中,我正在逐渐从RXJava过渡到协程。我有一种情况,我需要暂停执行并等待回调返回的结果。我已经将我的RXJava方法转换为以以下方式使用协程:
suspend fun fetchProducts(ids: List<String>) = suspendCoroutine<List<ProductItem>> { continuation ->
val getProducts = repo.search(ids, null, null)
getProducts.subscribe(
{ callResult ->
productRequestInProgress.postValue(false)
continuation.resume(callResult.result())
},
{ error ->
productRequestInProgress.postValue(false)
//continuation.resumeWithException(t)
}
)
}
我调用fetchProducts方法从. mapbypage函数,但我得到消息"挂起函数'await'应该只从协程或另一个挂起函数">调用。关于如何正确调用fetchProducts有什么想法吗?函数并等待mapByPage函数的结果?这就是我得到错误消息的地方。由于
val dataSourceFactory = SearcherSingleIndexDataSource.Factory(searcher) { hit ->
Product(hit.json.getValue("id").jsonPrimitive.content)
}.mapByPage { it ->
viewModelScope.launch {
fetchProducts(it.mapNotNull { it.id })
}.await()
}
可以将协程封装在runBlocking块中。
运行一个新的协程并可中断地阻塞当前线程,直到它的完成。
…
它的设计目的是将常规的阻塞代码与以挂起风格编写的库
.mapByPage { it ->
runBlocking {
fetchProducts(it.mapNotNull { it.id })
}
}
yesawait()
被定义为挂起函数,suspend关键字就像一个信号,表明这个函数是一个长时间运行的任务,因此应该异步运行,因为await()
是一个挂起函数,如果我们允许在没有程序或其他挂起函数的情况下执行它,这意味着我们正在对错误运行的任务进行阻塞调用,因此我们不允许这样做。
因此挂起函数可以从协程或其他挂起函数中调用,该规则保证长时间运行的任务在挂起函数中不会阻塞主线程。
你也使用启动,你应该使用async
功能,而不是launch
启动是火和忘记的工作,async
是使用当你想要一个结果回来后完成。
一般来说,如果你的suspend函数有一个返回类型,使用async
,使用launch,否则
如果你想要一个List
的产品返回,你可以使用async,如下所示。
viewModelScope.launch{
val products = viewModelScope.async(Dispathers.Default) { // Dispathers.Default is used for CPU intensive work, even if you don't pass anything Dispathers.Default is there , use Dispacther.IO for IO , Dispathers.Main for working with views in coroutine , like updating text view
fetchProducts(it.mapNotNull { it.id })
}.await()
}