【问题标题】:Recyclerview Duplicate Values with LiveData onBackPressed in FragmentRecyclerview 在片段中使用 LiveData onBackPressed 重复值
【发布时间】:2020-09-05 23:09:30
【问题描述】:

我有一个负载更多的回收器视图,但我无法将值存储在数据库中。因此,当我加载数据时,一切正常。当我导航到另一个片段并单击 onBackPressed 时,会出现问题,再次调用观察者的 onChanged,它为我提供了从 API 调用的最后一个值。然后正如您在下面的代码中看到的那样,它们会自动添加到列表中并在 UI 中发布

 productsViewModel.productsObject.observe(viewLifecycleOwner, Observer { result ->
        if (result.status != Status.LOADING) {
            (activity as MainActivity?)!!.dismissProgressDialog(getView())
            if (result.status == Status.SUCCESS && result.data != null) {
                val productsResult = parseObject(result.data.asJsonObject)
                if (!productsResult.isNullOrEmpty()) {
                    products.addAll(productsResult)
                    productAdapter.submitList(products)
                    progressBar.visibility = View.GONE
                    numberSearch.text = products.size.toString() + "/" + total + " " + resources.getString(R.string.items_found)
                } else if (result.status == Status.ERROR) {
                    if (result.message.isNullOrBlank())
                        Utils.showSnackBar(requireContext(), view, getString(R.string.something_wrong_try_again), true)
                    else
                        Utils.showSnackBar(requireContext(), view, result.message, true)
                }
            }
        }
    })

【问题讨论】:

  • onChanged 将在碎片恢复时使用 LiveData 中的先前值调用。您可以做的一件事是在 LiveData 的 getter 中,您可以清除它并返回。这样每次调用 observe 时都会得到一个新的 LiveData。
  • 如何清除liveData?
  • 在您的实时数据获取器中,在您返回实时数据之前,使用livedata = MutableLiveData() 重新初始化它,以便您收到新的实时数据。
  • 好主意让我试试。昨天晚上我从转换切换到使用 MutableLiveData

标签: android kotlin mvvm viewmodel observers


【解决方案1】:

我认为您没有正确观察您的result

例如,如果result 的值为Status.LOADING,会发生什么?在你进入那个区块之后,也许还有其他你没有处理的情况。我们不知道,因为没有其他 whenelse if 块。

另一种更“干净”的方式是:

productsViewModel.productsObject.observe(viewLifecycleOwner, Observer { result ->
    when(result.status) {
        Status.LOADING -> manageLoading()
        Status.SUCCESS -> manageSuccess()
        Status.ERROR -> manageError()
        else -> manageBaseCase()
    }
}

因此,它并非全部嵌入一个独特的if 块中,从而使管理更易于理解。

在您的 Fragment 中,您应该手动发送一个事件来“重置”LiveData 的实际状态,这样您就可以确保不会有重复的项目。

您的 Fragment 可能如下所示:

class ProductsFragment : Fragment() {
    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        return inflater.inflate(R.layout.product_fragment, container, false)
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        observe()
        productsViewModel.send(Event.Load)
    }
}

【讨论】:

  • 其实并不是这样,因为fragment从栈中弹回时的状态其实是success。
  • 你的 ViewModel 在哪里初始化?在MainActivityFragment
  • ovViewCreated 中的片段
  • 在你observe() 你的状态在onViewCreated() 之后,你应该发送一个事件来重置实际状态。 productsViewModel.send(Event.Load)
  • 完成。很高兴它的工作,让我知道答案是否足够清楚,否则我会尝试进一步改进它。
猜你喜欢
  • 1970-01-01
  • 2013-08-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-08-19
  • 1970-01-01
  • 2018-07-24
  • 1970-01-01
相关资源
最近更新 更多