gpt4 book ai didi

android - 如何在Interactor/UseCase中获取CoroutineScope

转载 作者:行者123 更新时间:2023-12-02 19:33:49 25 4
gpt4 key购买 nike

考虑这个用例:

class GetPhotosUseCase(
private val photosRepository: IPhotosRepository,
private val favoritesRepository: IFavoritesRepository
) : IGetPhotosUseCase {

override suspend fun getPhotos(): List<Photo> {
val photos = photosRepository.getPhotos()
val favoriteIds = favoritesRepository.getFavoriteIds()
return photos.map {
it.copy(isFavorite = favoriteIds.contains(it.id))
}
}

}

interface IPhotosRepository {

suspend fun getPhotos(): List<Photo>

}

interface IFavoritesRepository {

suspend fun getFavoriteIds(): List<Int>

}

我从两个不同的来源获取数据并将它们组合起来。现在,这是连续运行的。当我想并行运行 photosRepository.getPhotos()favoritesRepository.getFavoriteIds() 以节省执行时间时,我的幼稚方法是:

override suspend fun getPhotos(): List<Photo> {
val photosDeferred = GlobalScope.async { photosRepository.getPhotos() }
val favoriteIdsDeferred = GlobalScope.async { favoritesRepository.getFavoriteIds() }
return applyFavoritesToPhotos(photosDeferred.await(), favoriteIdsDeferred.await())
}

private fun applyFavoritesToPhotos(photos: List<Photo>, favoriteIds: List<Int>) = photos.map {
it.copy(isFavorite = favoriteIds.contains(it.id))
}

不鼓励使用GlobalScope,因为当调用者的生命周期结束时,作业不会被取消。

由于我的用例不知道调用者的生命周期,它应该使用哪个范围?将范围传递给用例是否是一个不错的解决方案,例如:

   override suspend fun getPhotos(scope: CoroutineScope): List<Photo> {
val photosDeferred = scope.async { photosRepository.getPhotos() }
val favoriteIdsDeferred = scope.async { favoritesRepository.getFavoriteIds() }
return applyFavoritesToPhotos(photosDeferred.await(), favoriteIdsDeferred.await())
}

或者这里理想的解决方案是什么?用例是否应该返回一个Deferred并让调用者await它?

最佳答案

不要将范围传递给您的UseCase,因为您会破坏干净的架构。相反,只需将您的函数保持为挂起即可。如果您希望函数并发,只需将它们包装在async block 中。

ViewModel 中使用 UseCase 并使用 ViewModelScope 调用挂起函数。

override suspend fun getPhotos(): List<Photo> {
val photos = async { photosRepository.getPhotos() }
val favoriteIds = async { favoritesRepository.getFavoriteIds() }

return photos.await().map {
it.copy(isFavorite = favoriteIds.await().contains(it.id))
}
}

编辑

正如前面提到的async需要一个作用域,一个好的解决方案是在UseCase 其工作是确定将同时运行这两个 async 任务的单个协程的范围。

val customScope = CoroutineScope(Dispatchers.Main)

override suspend fun getPhotos(): List<Photo> {
customScope.launch {
val photos = async { photosRepository.getPhotos() }
val favoriteIds = async { favoritesRepository.getFavoriteIds()}
}
.
.
.
}

关于android - 如何在Interactor/UseCase中获取CoroutineScope,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61396762/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com