首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么Flow (kotlinx.coroutines.flow)不使用Retry,即使我在Android中手动设置为null?

为什么Flow (kotlinx.coroutines.flow)不使用Retry,即使我在Android中手动设置为null?
EN

Stack Overflow用户
提问于 2022-09-01 07:45:32
回答 1查看 141关注 0票数 0

因此,基本上,在snackbar操作按钮上,如果用户单击Retry,我想重试API调用。

我使用了具有Flow的核心MVVM架构。我甚至还使用了视图模型和视图之间的流。请注意,我已经在视图和ViewModel之间使用了livedata,但是现在需求已经改变了,我只能使用Flow。此外,我也不使用和共享或状态流,这不是必需的。

代码:片段:

代码语言:javascript
复制
 private fun apiCall() {
    viewModel.fetchUserReviewData()
}

private fun setObservers() {
    lifecycleScope.launch {
        viewModel.userReviewData?.collect {
            LogUtils.d("Hello it: " + it.code)
            setLoadingState(it.state)
            when (it.status) {
                
                Resource.Status.ERROR -> showErrorSnackBarLayout(-1, it.message, {
// Retry action button logic
                    viewModel.userReviewData = null
                    apiCall()
                })
            }
        }
    }

视图模型:

代码语言:javascript
复制
var userReviewData: Flow<Resource<ReviewResponse>>? = emptyFlow<Resource<ReviewResponse>>()

fun fetchUserReviewData() {
    LogUtils.d("Hello fetchUserReviewData: " + userReviewData)
    userReviewData = flow {
        emit(Resource.loading(true))

        repository.getUserReviewData().collect {
            emit(it)
        }
    }
}

在ViewModel中编辑:

代码语言:javascript
复制
 //  var userReviewData = MutableStateFlow<Resource<ReviewResponse>>(Resource.loading(false))
var userReviewData = MutableSharedFlow<Resource<ReviewResponse>>()

fun fetchUserReviewData() {
    viewModelScope.launch {
        userReviewData.emit(Resource.loading(true))
        repository.getUserReviewData().collect {
            userReviewData.emit(it)
        }
    }
}

override fun onCreate() {}

}

在活动中编辑:

代码语言:javascript
复制
private fun setObservers() {
    lifecycleScope.launchWhenStarted {
        viewModel.userReviewData.collect {
            setLoadingState(it.state)
            when (it.status) {
                Resource.Status.SUCCESS ->
                    if (it.data != null) {
                        val reviewResponse: ReviewResponse = it.data
                        if (!AppUtils.isNull(reviewResponse)) {
                            setReviewData(reviewResponse.data)
                        }
                    }
                Resource.Status.ERROR -> showErrorSnackBarLayout(it.code, it.message) {
                    viewModel.fetchUserReviewData()
                }
            }
        }
    }
}

现在,我只有一个疑问,我是使用状态1还是共享状态?我看到菲利普拉克纳视频和理解的区别,但仍在考虑使用什么!

问题是我们只支持面向肖像,但是未来的需求会是什么呢?在这种情况下,我认为我必须使用state one,这样它才能在配置更改中存活下来!不知道该怎么办!

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-09-02 17:30:57

由于单一责任原则,ViewModel应该单独更新其流以显示最新的请求数据,而不是必须取消正在进行的请求并从片段端重新订阅新的请求。

这是你可以做的一种方法。使用MutableSharedFlow触发获取请求,使用flatMapLatest重新启动新请求的下游流。

通道也可以用作触发器,但它与MutableSharedFlow相比要简洁一些。

代码语言:javascript
复制
//In ViewModel
private val fetchRequest = MutableSharedFlow<Unit>(replay = 1, BufferOverflow.DROP_OLDEST)

var userReviewData = fetchRequest.flatMapLatest {
    flow {
        emit(Resource.loading(true))
        emitAll(repository.getUserReviewData())
    }
}.shareIn(viewModelScope, SharingStarted.WhlieSubscribed(5000), 1)

fun fetchUserReviewData() {
    LogUtils.d("Hello fetchUserReviewData: " + userReviewData)
    fetchRequest.tryEmit(Unit)
}

上面的现有片段代码应该可以使用这一点,但是您不再需要?空安全调用,因为流是不可空的。

但是,,如果协同线对视图做了任何操作,则应该使用viewLifecycle.lifecycleScope而不是仅使用lifecycleScope

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73565830

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档