【问题标题】:How to handle multiple API calls in android MVI architecture (unidirectional dataflow)?如何处理android MVI架构中的多个API调用(单向数据流)?
【发布时间】:2021-06-29 15:10:09
【问题描述】:

所以我正在关注 MVI 架构以及如何处理多个 api 调用结果,所以我的代码如下所示,我使用 https://github.com/RohitSurwase/AAC-MVI-Architecture 作为参考

Modal.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)
        }
    ))
}

Fragment.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 来加载 cmets,所以我尝试将实现更改为类似

Modal.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()
}

我们将在片段中

Fragment.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 它将重新触发加载 cmets,这是不希望的。 如何处理多个 api 调用,以便更改一个 API 调用的状态不会重新触发其他 api 调用中的事件

【问题讨论】:

    标签: android kotlin


    【解决方案1】:

    对于这种情况,我会将这两个调用与以下内容结合起来:

    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”将代表帖子及其 cmets 的列表,您可以将其更改为包含两者的内容。

    例如,在 fetchPostFeed 中,您可以同时调用两个端点,或者一个接一个地等待两个端点返回结果并将它们分别发布到成功响应中,例如“postList”和“commList”。 另一种选择是使用映射器将它们组合到一个新的数据类中(即帖子列表,每个帖子都有各自的 cmets 列表)。

    以 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())
    

    【讨论】:

      猜你喜欢
      • 2021-07-17
      • 1970-01-01
      • 2020-07-17
      • 1970-01-01
      • 2014-07-14
      • 2019-04-24
      • 1970-01-01
      • 2015-06-03
      • 1970-01-01
      相关资源
      最近更新 更多