android - 弹出片段后的多个 LiveData 观察者
问题描述
问题
摘要:在导航到新的 Fragment、弹出新的 Fragment 并返回到原始 Fragment 后,在一个 Fragment 中触发了多个LiveData Observer 。
详细信息:该架构由MainActivity组成,该 MainActivity承载HomeFragment作为MainActivity导航图中的起始目的地。在 HomeFragment 中是一个以编程方式膨胀的PriceGraphFragment。HomeFragment正在使用导航组件来启动一个新的子Fragment ProfileFragment。按下后,ProfileFragment 被弹出,应用程序返回到承载 PriceGraphFragment 的 HomeFragment。PriceGraphFragment 是多次调用 Observer 的地方。
我正在记录观察者发出的 HashMap 的哈希码,当我转到配置文件片段、弹出配置文件片段并返回价格片段时,它显示了 2 个唯一的哈希码。这与我在不启动配置文件片段的情况下旋转屏幕时从 HashMap 看到的一个哈希码相反。
执行
在 HomeFragment 中启动新 ProfileFragment 的导航组件。
view.setOnClickListener(Navigation.createNavigateOnClickListener( R.id.action_homeFragment_to_profileFragment, null))
在 Fragment (PriceGraphFragment) 中创建ViewModel 。ViewModel 已经被记录,拥有多个 Observer 的数据只有在 ViewModel 中初始化过一次。
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) priceViewModel = ViewModelProviders.of(this).get(PriceDataViewModel::class.java) }
在原始 Fragment (PriceGraphFragment) 中侦听来自ViewModel的数据。这会被多次调用,但是在加载 Fragment 时只希望有一个 Observer。
priceViewModel.graphLiveData.observe( this, Observer { priceGraphDataMap: HashMap<Exchange, PriceGraphLiveData>? -> // This is being called multiple times. })
尝试的解决方案
- 在onCreate()方法
中创建Fragment的ViewModel 。
priceViewModel = ViewModelProviders.of(this).get(PriceDataViewModel::class.java)
使用 Fragment 的 Activity 和子 Fragment 的父 Fragment 创建 ViewModel。
priceViewModel = ViewModelProviders.of(activity!!).get(PriceDataViewModel::class.java)
priceViewModel = ViewModelProviders.of(parentFragment!!).get(PriceDataViewModel::class.java)
- 将创建 Observers 的方法移动到 Fragment 的onCreate()和onActivityCreated()方法。
- 在方法中使用
viewLifecycleOwner
代替LifecycleOwner。this
observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer)
- 存储在 ViewModel 中显示为重复的 HashMap 数据,而不是 Fragment。
ChildFragmentManager
使用和SupportFragmentManager
(在活动级别)启动子片段。
类似问题和建议的解决方案
- https://github.com/googlesamples/android-architecture-components/issues/47
- https://medium.com/@BladeCoder/architecture-components-pitfalls-part-1-9300dd969808
- https://plus.google.com/109072532559844610756/posts/Mn9SpcA5cHz
下一步
- 也许问题与在ParentFragment ( HomeFragment ) 中创建嵌套的ChildFragment ( PriceGraphFragment )有关?
onViewCreated()
父片段
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()
}
- 测试用 RxJava 可观察对象替换 LiveData 对象。
解决方案
这基本上是架构中的一个错误。你可以在这里阅读更多关于它的信息。您可以通过getViewLifecycleOwner
在observer
.
像这样:
mViewModel.methodToObserve().observe(getViewLifecycleOwner(), new Observer<Type>() {
@Override
public void onChanged(@Nullable Type variable) {
并把这段代码onActivityCreated()
作为使用getViewLifecycleOwner
需要的视图。
推荐阅读
- laravel - 在 Laravel 中,为什么 !$request->expectsJson() 确定用户是否经过身份验证?
- ios - SwiftUI 是否可以在 ForEach 中传递绑定范围?
- python - 如何获取我的 Arduino 连接的串行端口号?
- vue.js - 标签未使用工作箱缓存
- r - 根据另一个 df 更改 df1 列中的值
- javascript - 如何打开和关闭 bul:但仅使用 1 个按钮?
- php - $_SERVER['SERVER_ADDR'] 总是给出服务器的主 IP,而不是 php 中实际运行的服务器 IP
- python - Python脚本用映射表替换多个字符串
- javascript - 未捕获的类型错误:尝试显示数据时无法读取未定义的属性“0”
- reactjs - React Material-UI 网格布局未按预期工作