【问题标题】:How to prevent viewmodel to fire again my Loading bar如何防止视图模型再次触发我的加载栏
【发布时间】:2020-03-10 18:52:03
【问题描述】:

我有一个加载产品列表的片段,然后我转到另一个片段,但是当我回来时,Resource.Loading 再次触发显示在我的进度条中

我正在使用导航组件,我知道我应该处理我的状态,但我的问题是这个。

我知道 livedata 将存储我的数据,然后当弹回到这个片段时,它会立即从 livedata 本身加载它,而不是再次检索它,但是,它也会在我的数据列表上方显示我的进度条,我知道那是因为我的 emit(Resource.Loading()) 来自我的 viewModel,但是...

如果我从另一个片段返回并重新创建此 onActivityCreated ,是否有办法不显示此进度或不发出 Loading 状态?

代码

我的片段

 override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)

        viewModel.fetchProductList()
            .observe(viewLifecycleOwner, Observer {

                when (it) {
                    is Resource.Loading -> {
                        showProgress()
                    }
                    is Resource.Success -> {
                        hideProgress()
                        landingAdapter.itemList = it.data
                        if (landingAdapter.itemCount == 0) {
                            Toast.makeText(
                                requireContext(),
                                "No items yet",
                                Toast.LENGTH_SHORT
                            ).show()
                        }
                        landingAdapter.notifyDataSetChanged()
                    }
                    is Resource.Failure -> {
                        hideProgress()
                    }
                }
            })
    }

视图模型

fun fetchProductList() = liveData(Dispatchers.IO) {
        emit(Resource.Loading())
        try{
            val getProductList = repo.getProductList()
            emit(getProductList)
        }catch (e:Exception){
            emit(Resource.Failure(e))
        }
    }

此时我认为在 popBackstack 上重新创建片段时再次发出 Resource.Loading() 再次向我显示我的进度对话框

我尝试过使用事件包装器,但它也一样

编辑

由于我使用的是 livedata-ktx ,我不想在我的视图模型构造函数中加载我的数据,而是我想在我的片段中只处理一次

谢谢

【问题讨论】:

    标签: android kotlin mvvm android-viewmodel android-navigation


    【解决方案1】:

    我建议添加第四个状态Resource.Idle,当当前状态为Resource.Loading 时,当用户离开时发出,当观察状态时,当它的值为Resource.Idle 时不采取任何行动。

    【讨论】:

    • 感谢您的回答,非常合理,我喜欢它,问题是我需要在第一次通话中嵌套一个新的观察者,我不想那样做,谢谢您回答
    • 好的。另一个建议是使用 Resource.Loading 对象,因此它只使用一次。如果您有兴趣,请查看:github.com/android/architecture-samples/blob/master/app/src/…
    • 我认为另一个 state of sealed class 在这种特殊情况下是多余的 @CoffeeBreak @Mohsin
    【解决方案2】:

    fetchProductList() function 不是 variable 称它为returns 新的LiveData<Resource> 对象。而是尝试不使用函数:-

    val productListLiveData: LiveData<Resource> = liveData(Dispatchers.IO) {
        emit(Resource.Loading())
        try {
            val getProductList = repo.getProductList()
            emit(getProductList)
        } catch (e:Exception){
            emit(Resource.Failure(e))
        }
    }
    

    fragment 中观察它。

    【讨论】:

    • 实际上,我正在向它传递一个我在问题中没有指定的参数,soryy
    • 然后你可以使用viewModelFactory直接将参数传递给viewModel,每次使用builder lambda创建一个新的liveData对象是不好的做法@CoffeeBreak
    • 我已经有一个 viewModelFactory 可以将我的 repo 注入到 viewmodel 中,我需要做的不是在该函数内触发 emit(Resource.Loading()) 时触发 progressBar
    • 如果创建了依赖图,在片段内,parameters也可以与repo一起注入@seeBindsInstance
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-05
    • 1970-01-01
    相关资源
    最近更新 更多