New*_*zal 7 suspend kotlin kotlin-flow
在审查用 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)
}
Run Code Online (Sandbox Code Playgroud)
只是流动
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."))
}
}
}
Run Code Online (Sandbox Code Playgroud)
只是暂停
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
}
}
Run Code Online (Sandbox Code Playgroud)
这三个都是不同的项目,不要被代码所困扰,这些只是我遇到过的项目,我分享是为了展示示例,但我想在这里提请您注意的是,有时只有暂停使用function,有时只使用Flow,有时两者都使用。这是什么原因呢?你能详细解释一下吗?我试图将其纳入我的逻辑
Ten*_*r04 12
suspend函数对于以暂停、同步的方式检索单个项目是有意义的。
当您决定开始收集时,流程会随着时间的推移返回多个项目。它们通常用于监视随时间变化的事物,以检索事物的最新值。例如,每次数据库中的某些内容发生更改时,来自数据库的流都可以发出新值。
使用检索 Flow 的挂起函数将两者结合起来几乎没有意义。这是因为 Flow 本身是一个轻量级对象,通常不需要任何前期、耗时的工作来检索和创建。
避免在返回流时创建函数的原因suspend是它使用起来更加麻烦。在某些情况下,您可能希望传递流而不收集它,并且您不希望仅仅为了获取流而启动协程。或者,您可能只想使用这种漂亮、简洁的语法来创建专用的集合协程:
someUseCase.retrieveSomeFlow()
.onEach { ... }
.launchIn(someScope)
Run Code Online (Sandbox Code Playgroud)
代替:
someScope.launch {
someUseCase.retrieveSomeFlow().collect {
...
}
}
Run Code Online (Sandbox Code Playgroud)
如果您必须检索某些内容作为流程基础的密钥,则可能会出现例外情况。例如,从 API 检索用户 ID,然后返回使用该用户 ID 来获取流的项目的流。但即使这样通常也是不必要的,因为您可以将该 ID 检索放入流程中。例如:
fun getUserItems(): Flow<UserItem> = flow {
val userId = someAPI.retrieveUserId() // calling a suspend function
emitAll(someAPI.getUserItemsFlow(userId))
}
Run Code Online (Sandbox Code Playgroud)
这样做的唯一缺点是,如果您多次收集流量,则每次开始收集时都必须重新检索用户 ID。
| 归档时间: |
|
| 查看次数: |
2472 次 |
| 最近记录: |