在审查用 kotlin 编写的一些代码时,有件事引起了我的注意。我在一些项目中查看领域层,在一些项目中,我看到挂起功能和 Flow 一起使用,而在一些项目中,我看到只使用 Flow。
例如暂停和流动在一起 :
class FetchMovieDetailFlowUseCase @Inject constructor(
private val repository: MovieRepository
) : FlowUseCase<FetchMovieDetailFlowUseCase.Params, State<MovieDetailUiModel>>() {
data class Params(val id: Long)
override suspend fun execute(params: Params): Flow<State<MovieDetailUiModel>> =
repository.fetchMovieDetailFlow(params.id)
}
只是流动
class GetCoinUseCase @Inject constructor(
private val repository: CoinRepository
){
operator fun invoke(coinId:String): Flow<Resource<CoinDetail>> = flow {
try {
emit(Resource.Loading())
emit(Resource.Success(coin))
}catch (e:HttpException){
emit(Resource.Error(e.localizedMessage ?: "An unexpected error occured"))
}catch (e:IOException){
emit(Resource.Error("Couldn't reach server. Check your internet connection."))
}
}
}
只是暂停
class GetLatestNewsWithAuthorsUseCase(
private val newsRepository: NewsRepository,
private val authorsRepository: AuthorsRepository,
private val defaultDispatcher: CoroutineDispatcher = Dispatchers.Default
) {
suspend operator fun invoke(): List<ArticleWithAuthor> =
withContext(defaultDispatcher) {
val news = newsRepository.fetchLatestNews()
val result: MutableList<ArticleWithAuthor> = mutableListOf()
// This is not parallelized, the use case is linearly slow.
for (article in news) {
// The repository exposes suspend functions
val author = authorsRepository.getAuthor(article.authorId)
result.add(ArticleWithAuthor(article, author))
}
result
}
}
这三个都是不同的项目,不要被代码所困扰,这些只是我遇到过的项目,我分享是为了展示示例,但我想在这里提请您注意的是,有时只有暂停使用function,有时只使用Flow,有时两者都使用。这是什么原因呢?你能详细解释一下吗?
我试图将其纳入我的逻辑
suspend
函数对于以暂停、同步的方式检索单个项目是有意义的。
当您决定开始收集时,流程会随着时间的推移返回多个项目。它们通常用于监视随时间变化的事物,以检索事物的最新值。例如,每次数据库中的某些内容发生更改时,来自数据库的流都可以发出新值。
使用检索 Flow 的挂起函数将两者结合起来几乎没有意义。这是因为 Flow 本身是一个轻量级对象,通常不需要任何前期、耗时的工作来检索和创建。
避免创建函数的原因suspend
当返回流时,它使得使用起来更加麻烦。在某些情况下,您可能希望传递流而不收集它,并且您不希望仅仅为了获取流而启动协程。或者,您可能只想使用这种漂亮、简洁的语法来创建专用的集合协程:
someUseCase.retrieveSomeFlow()
.onEach { ... }
.launchIn(someScope)
代替:
someScope.launch {
someUseCase.retrieveSomeFlow().collect {
...
}
}
如果您必须检索某些内容作为流程基础的密钥,则可能会出现例外情况。例如,从 API 检索用户 ID,然后返回使用该用户 ID 来获取流的项目的流。但即使这样通常也是不必要的,因为您可以将该 ID 检索放入流程中。例如:
fun getUserItems(): Flow<UserItem> = flow {
val userId = someAPI.retrieveUserId() // calling a suspend function
emitAll(someAPI.getUserItemsFlow(userId))
}
这样做的唯一缺点是,如果多次收集流量,则每次开始收集时都必须重新检索用户 ID。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)