【问题标题】:ViewModel prevent refetching of dataViewModel 防止重新获取数据
【发布时间】:2020-08-18 05:16:13
【问题描述】:

我的 viewModel 重新获取我的数据,导致我的微光在每次我到达这个片段时继续执行,并且数据被重新获取,这使得我在 Firebase 上的账单增加了

如何防止每次我的片段弹出时再次重新获取数据?

在我看来

 viewModel.fetchShops(location).observe(viewLifecycleOwner, Observer {
            when(it){
                is Resource.Loading -> {
                    shimmer.visibility = View.VISIBLE
                    shimmer.startShimmer()}
                is Resource.Success -> {
                    shimmer.visibility = View.GONE
                    shimmer.stopShimmer()
                    adapter.setItems(it.data)
                }
                is Resource.Failure -> {
                    Toast.makeText(requireContext(),"Error fetching data",Toast.LENGTH_SHORT).show()
                }
            }
        })

我在我的onViewCreated() 中调用它,所以每次这个片段重新创建我的Resource.LoadingfetchShops(location) 并再次获取到我的数据库时,我希望它每次返回时只获取一次这个片段,有什么想法吗?

视图模型

   fun fetchShops(location:String) = liveData(Dispatchers.IO) {
            emit(Resource.Loading())
            try{
                emit(repo.fetchShops(location))
            }catch (e:Exception){
                emit(Resource.Failure(e))
            }
        }

【问题讨论】:

标签: android firebase android-fragments kotlin


【解决方案1】:

每次调用 fetchShops() 时,您都会创建一个新的 LiveData 实例。这意味着任何之前创建的LiveData(以及它之前存储的值)都会丢失。

相反,您应该Tranform your LiveData 使用您的location 作为输入,以根据liveData with Transformations 创建您的liveData { } 块。

private val locationQuery = MutableLiveData<String>

// Use distinctUntilChanged() to only requery when the location changes
val shops = locationQuery.distinctUntilChanged().switchMap { location ->
    // Note we use viewModelScope.coroutineContext to properly support cancellation
    liveData(viewModelScope.coroutineContext + Dispatchers.IO) {
        emit(Resource.Loading())
        try{
            emit(repo.fetchShops(location))
        }catch (e:Exception){
            emit(Resource.Failure(e))
        }
    }
}

fun setLocation(location: String) {
    locationQuery.value = location
}

然后您可以通过更新 Fragment 来使用它:

// Set the current location
viewModel.setLocation(location)

// Observe the shops
viewModel.shops.observe(viewLifecycleOwner, Observer {
        when(it){
            is Resource.Loading -> {
                shimmer.visibility = View.VISIBLE
                shimmer.startShimmer()}
            is Resource.Success -> {
                shimmer.visibility = View.GONE
                shimmer.stopShimmer()
                adapter.setItems(it.data)
            }
            is Resource.Failure -> {
                Toast.makeText(requireContext(),"Error fetching data",Toast.LENGTH_SHORT).show()
            }
        }
    })

【讨论】:

  • 如此干净,非常感谢@ianhanniballake,最后一个问题,我们是否总是需要使用 distinctUntilChanged() 进行单次操作也与 switchmap ?谢谢
  • @CoffeeBreak - 好吧,通常你只会在位置实际发生变化时调用setLocationdistinctUntilChanged() 只是意味着您可以一次又一次地将其设置为相同的值而无需重新加载
猜你喜欢
  • 1970-01-01
  • 2017-11-21
  • 1970-01-01
  • 2020-05-18
  • 2020-12-31
  • 1970-01-01
  • 1970-01-01
  • 2013-03-12
  • 2022-01-21
相关资源
最近更新 更多