android - 如何处理android MVI架构中的多个API调用(单向数据流)?
问题描述
所以我正在关注 MVI 架构以及如何处理多个 api 调用结果,所以我的代码如下所示,我使用https://github.com/RohitSurwase/AAC-MVI-Architecture作为参考
模态.kt
data class HomeViewState(val postListState: PostListState)
sealed class PostListState {
object Loading : PostListState()
data class Success(val postList: List<Post>) : PostListState()
data class Error(val message: String) : PostListState()
}
ViewModal.kt
private fun fetchPostFeed() {
composite.add(postUseCase.fetchPostList().subscribe(
{ postList ->
viewState = viewState.copy(postListState = PostListState.Success(postList))
},
{ error ->
viewState = viewState.copy(
postListState = PostListState.Error(
message = error.localizedMessage ?: "Something went wrong while fetching postlist!!!"
)
)
Timber.e(error)
}
))
}
片段.kt
override fun renderViewState(viewState: HomeViewState) {
when (viewState.postListState) {
PostListState.Loading -> loadPosts()
is PostListState.Success -> showPostListToUI(viewState.postListState.postList)
is PostListState.Error -> showErrorLayout(viewState.postListState.message)
}
}
所以流程是当 ViewModel 初始化默认状态设置为PostListState.Loading时,这个状态更改片段的renderViewState()被调用,它发出加载事件,由fetchPostFeed()中的视图模型处理,以防万一成功或错误。
问题
现在我也想进行 API 调用来加载评论,所以我尝试将实现更改为类似
模态.kt
data class HomeViewState(val postListState: PostListState, val commentsState: CommentsState)
sealed class PostListState {
object Loading : PostListState()
data class Success(val postList: PagedList<Post>) : PostListState()
data class Error(val message: String) : PostListState()
}
sealed class CommentsState {
object Loading : CommentsState()
data class Success(val commList: List<Comments>) : CommentsState()
data class Error(val message: String) : CommentsState()
}
在片段中,我们将
片段.kt
override fun renderViewState(viewState: HomeViewState) {
when (viewState.postListState) {
PostListState.Loading -> loadPosts()
is PostListState.Success -> showPostListToUI(viewState.postListState.postList)
is PostListState.Error -> showErrorLayout(viewState.postListState.message)
}
when (viewState.commentsState) {
CommentsState.Loading -> loadComments()
is CommentsState.Success -> showCOmments(viewState.commentsState.commList)
is CommentsState.Error -> showErrorLayout(viewState.commentsState.message)
}
}
现在的事情是假设 post fetch 较早完成并且状态更新为PostListState.Success并且如果评论状态仍处于CommentsState.Loading它将重新触发评论的加载,这是不希望的。如何处理多个 api 调用,以便更改一个 API 调用的状态不会重新触发其他 api 调用中的事件
解决方案
对于这种情况,我会将这两个调用与以下内容结合起来:
sealed class PostListState {
object Loading : PostListState()
data class Success(val postList: List<Post>, val commList: List<Comments>) : PostListState()
data class Error(val message: String) : PostListState()
}
这里的名称“PostList”将代表帖子列表及其评论,您可以将其更改为包含两者的内容。
例如,在 fetchPostFeed 中,您可以同时调用两个端点,或者一个接一个地等待两者返回结果并将它们分别发布到成功响应中,如“postList”和“commList”。另一种选择是使用映射器将它们组合在一个新的数据类中(即一个帖子列表,每个帖子都有各自的评论列表)。
例如,使用 RxJava 会是这样的:
Observable.zip(
FetchPostList().subscribeOn(Schedulers.io()),
FetchCommentList().subscribeOn(Schedulers.io()),
BiFunction { firstResponse: PostList,
secondResponse: CommentList ->
Pair(firstResponse, secondResponse)
})
.flatMap { resultPair ->
Observable.just(PostListState.Success(resultPair.first, resultPair.second))
}
.onErrorReturn(Error)
.startWith(Loading)
.observeOn(AndroidSchedulers.mainThread())
推荐阅读
- ios - 如何获取代码覆盖率信息?
- facebook - 如何在 Facebook Messaging API 中将消息设置为已读?(欧洲)
- python - Django REST 框架 TokenAuthentication 返回匿名用户
- automation - 如何使用带有脚本的模板自动进行视频编辑?
- c - 'gcc' 不是内部或外部命令、可运行程序或批处理文件。: C on VS
- javascript - flexbox 内的项目不可交互
- python-3.x - Django 将动态字段添加到前端,然后将其插入到模型中
- flutter - Flutter 全局定义按钮样式
- perl - perl 字符串到日期时间转换
- r - 如何用geom_rect在ggplot中填充geom_line图下方的区域?