混合搭配协程和 Rxjava
Mix and match Coroutines and Rxjava
Coroutines and RxJava3
我有以下方法,它首先调用一个挂起方法,然后在同一个启动范围内我对 RxJava 进行了 2 次调用。
我想知道是否有办法从 viewModelScope.launch
范围和 return fetchRecentUseCase.execute()
.
的结果中删除 Rxjava 代码
基本上,viewModelScope.launch
是否有可能 return listOfProducts
而不是在启动范围内执行所有操作?
fun loadRecentlyViewed() {
viewModelScope.launch {
val listOfProducts = withContext(Dispatchers.IO) {
fetchRecentUseCase.execute()
}
val listOfSkus = listOfProducts.map { it.sku }
if (listOfSkus.isNotEmpty()) {
loadProductUseCase.execute(listOfSkus)
.subscribeOn(schedulersFacade.io)
.flatMap(convertProductDisplayUseCase::execute)
.map { /* work being done */ }
.observeOn(schedulersFacade.ui)
.subscribeBy(
onError = Timber::e,
onSuccess = { }
)
}
}
}
挂起方法的用例
class FetchRecentUseCaseImp() {
override suspend fun execute(): List<Products> {
// Call to network
}
}
非常感谢
使用协同程序,return 异步生成单个项目的方法是使用 suspend
函数。因此,您无需启动协程,而是将函数标记为 suspend
并将阻塞或异步回调函数转换为非阻塞代码。
启动协程的地方通常是在 UI 交互(点击侦听器)时,或者在 类 首次创建时(在 Android,这是像在 ViewModel 中的地方构造函数或 Fragment 的 onViewCreated()
).
附带说明一下,对于任何 suspend
函数来说,期望调用者必须指定调度程序是违反惯例的。如果需要,它应该在内部委托,例如:
class FetchRecentUseCaseImp() {
override suspend fun execute(): List<Products> = withContext(Dispatchers.IO) {
// Synchronous call to network
}
}
但是如果您使用的是像 Retrofit 这样的库,您只需发出请求并 await()
它而不指定调度程序,因为 await()
本身就是一个挂起函数。
所以您的函数应该类似于:
suspend fun loadRecentlyViewed(): List<SomeProductType> {
val listOfSkus = fetchRecentUseCase.execute().map(Product::sku)
if (listOfSkus.isEmpty()) {
return emptyList()
}
return runCatching {
loadProductUseCase.execute(listOfSkus) // A Single, I'm assuming
.await() // Only if you're not completely stripping Rx from project
.map { convertProductDisplayUseCase.execute(it).await() } // Ditto for await()
.toList()
.flatten()
}.onFailure(Timber::e)
.getOrDefault(emptyList())
}
Coroutines and RxJava3
我有以下方法,它首先调用一个挂起方法,然后在同一个启动范围内我对 RxJava 进行了 2 次调用。
我想知道是否有办法从 viewModelScope.launch
范围和 return fetchRecentUseCase.execute()
.
基本上,viewModelScope.launch
是否有可能 return listOfProducts
而不是在启动范围内执行所有操作?
fun loadRecentlyViewed() {
viewModelScope.launch {
val listOfProducts = withContext(Dispatchers.IO) {
fetchRecentUseCase.execute()
}
val listOfSkus = listOfProducts.map { it.sku }
if (listOfSkus.isNotEmpty()) {
loadProductUseCase.execute(listOfSkus)
.subscribeOn(schedulersFacade.io)
.flatMap(convertProductDisplayUseCase::execute)
.map { /* work being done */ }
.observeOn(schedulersFacade.ui)
.subscribeBy(
onError = Timber::e,
onSuccess = { }
)
}
}
}
挂起方法的用例
class FetchRecentUseCaseImp() {
override suspend fun execute(): List<Products> {
// Call to network
}
}
非常感谢
使用协同程序,return 异步生成单个项目的方法是使用 suspend
函数。因此,您无需启动协程,而是将函数标记为 suspend
并将阻塞或异步回调函数转换为非阻塞代码。
启动协程的地方通常是在 UI 交互(点击侦听器)时,或者在 类 首次创建时(在 Android,这是像在 ViewModel 中的地方构造函数或 Fragment 的 onViewCreated()
).
附带说明一下,对于任何 suspend
函数来说,期望调用者必须指定调度程序是违反惯例的。如果需要,它应该在内部委托,例如:
class FetchRecentUseCaseImp() {
override suspend fun execute(): List<Products> = withContext(Dispatchers.IO) {
// Synchronous call to network
}
}
但是如果您使用的是像 Retrofit 这样的库,您只需发出请求并 await()
它而不指定调度程序,因为 await()
本身就是一个挂起函数。
所以您的函数应该类似于:
suspend fun loadRecentlyViewed(): List<SomeProductType> {
val listOfSkus = fetchRecentUseCase.execute().map(Product::sku)
if (listOfSkus.isEmpty()) {
return emptyList()
}
return runCatching {
loadProductUseCase.execute(listOfSkus) // A Single, I'm assuming
.await() // Only if you're not completely stripping Rx from project
.map { convertProductDisplayUseCase.execute(it).await() } // Ditto for await()
.toList()
.flatten()
}.onFailure(Timber::e)
.getOrDefault(emptyList())
}