所以我从来没有做过这样的事情,所以我不知道哪种方法更好。
现在,我有一个用例,它以流程返回。为了简单起见,我没有附上我的代码,但它与此非常相似。
class UseCase constructor(
private val userRepository: UserRepository,
private val carRepository: CarRepository
){
operator fun invoke(): Flow<Result<UserWithCars>>{
return flow {
try {
//UserRepository under the hood returns with a RxJava Single<List<User>> list
// But I converted to suspend fun with await() fun
val users = userRepository.getAllUsers().await()
fetchUserCars(users)
}catch (e: Exception){
emit(Result.Error())
}
}
}
private suspend fun fetchUserCars(userList: List<User>){
userList.forEach { user->
user.cars = try {
//REpository also returns with a Single<>
carRepository.getCarsByUserId(user.id).await()
}catch (e: Exception){
emptyList<Car>()
}
}
}
}
如果我没记错的话,foreach将会同步执行。我不确定,但我认为 foreach 可以以异步方式执行,但我不知道如何执行。
当时,我使用了 ansyc{} fun ,但我需要位于协程范围内。
以前,用户单是平面地图化的,汽车被提取到用户对象。
return users.flatMap { user->
fetchCars(user)
}
在 fetchCars() 方法中,我基本上将每个 userId 映射到查询汽车的 Single<>,因此我得到一个 List
那我可以再优化一下吗,还是现在就可以了?
您关于使用
async
的说法是正确的,但您可能忽略了这样一个事实:您需要创建一个新的协程作用域以允许启动多个子进程。另外,因为我们不返回汽车列表,而是直接将其添加给用户,所以我们可以使用 launch
代替 async
:
private suspend fun fetchUserCars(userList: List<User>){
coroutineScope {
userList.forEach { user->
launch {
user.cars = try {
//REpository also returns with a Single<>
carRepository.getCarsByUserId(user.id).await()
}catch (e: Exception){
emptyList<Car>()
}
}
}
}
}