首页 > 解决方案 > 弹出片段后的多个 LiveData 观察者

问题描述

问题

摘要:在导航到新的 Fragment、弹出新的 Fragment 并返回到原始 Fragment 后,在一个 Fragment 中触发了多个LiveData Observer 。

详细信息:该架构由MainActivity组成,该 MainActivity承载HomeFragment作为MainActivity导航图中的起始目的地。在 HomeFragment 中是一个以编程方式膨胀的PriceGraphFragment。HomeFragment正在使用导航组件来启动一个新的子Fragment ProfileFragment。按下后,ProfileFragment 被弹出,应用程序返回到承载 PriceGraphFragment 的 HomeFragment。PriceGraphFragment 是多次调用 Observer 的地方。

我正在记录观察者发出的 HashMap 的哈希码,当我转到配置文件片段、弹出配置文件片段并返回价格片段时,它显示了 2 个唯一的哈希码。这与我在不启动配置文件片段的情况下旋转屏幕时从 HashMap 看到的一个哈希码相反。

执行

  1. 在 HomeFragment 中启动新 ProfileFragment 的导航组件。

    view.setOnClickListener(Navigation.createNavigateOnClickListener( R.id.action_homeFragment_to_profileFragment, null))

  2. 在 Fragment (PriceGraphFragment) 中创建ViewModel 。ViewModel 已经被记录,拥有多个 Observer 的数据只有在 ViewModel 中初始化过一次。

    override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) priceViewModel = ViewModelProviders.of(this).get(PriceDataViewModel::class.java) }

  3. 在原始 Fragment (PriceGraphFragment) 中侦听来自ViewModel的数据。这会被多次调用,但是在加载 Fragment 时只希望有一个 Observer。

    priceViewModel.graphLiveData.observe( this, Observer { priceGraphDataMap: HashMap<Exchange, PriceGraphLiveData>? -> // This is being called multiple times. })

尝试的解决方案

  1. onCreate()方法 中创建FragmentViewModel 。priceViewModel = ViewModelProviders.of(this).get(PriceDataViewModel::class.java)
  2. 使用 Fragment 的 Activity 和子 Fragment 的父 Fragment 创建 ViewModel。
    priceViewModel = ViewModelProviders.of(activity!!).get(PriceDataViewModel::class.java)

    priceViewModel = ViewModelProviders.of(parentFragment!!).get(PriceDataViewModel::class.java)

  3. 将创建 Observers 的方法移动到 Fragment 的onCreate()onActivityCreated()方法。
  4. 在方法中使用viewLifecycleOwner代替LifecycleOwnerthisobserve(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer)
  5. 存储在 ViewModel 中显示为重复的 HashMap 数据,而不是 Fragment。
  6. ChildFragmentManager使用和SupportFragmentManager(在活动级别)启动子片段。

类似问题和建议的解决方案

下一步

父片段

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)
    user = viewModel.getCurrentUser()
     if (savedInstanceState == null) {
         fragmentManager
                ?.beginTransaction()
                ?.replace(binding.priceDataContainer.id, 
                   PriceGraphFragment.newInstance())
                ?.commit()
}

标签: androidandroid-fragmentskotlinandroid-navigationandroid-livedata

解决方案


这基本上是架构中的一个错误。你可以在这里阅读更多关于它的信息。您可以通过getViewLifecycleOwnerobserver.

像这样:

mViewModel.methodToObserve().observe(getViewLifecycleOwner(), new Observer<Type>() {
        @Override
        public void onChanged(@Nullable Type variable) {

并把这段代码onActivityCreated()作为使用getViewLifecycleOwner需要的视图。


推荐阅读