Android 弹出片段后的多个LiveData观察者 问题
摘要:导航到新片段、弹出新片段并返回原始片段后,片段中会触发多个LiveData观察者 详细信息:该体系结构由MainActivity组成,它承载一个HomeFragment,作为MainActivity的导航图中的起始目标。在HomeFragment中是一个通过编程方式膨胀的PriceGraphFragment。HomeFragment正在使用导航组件启动新的子片段ProfileFragment。按back键时,弹出ProfileFragment,应用程序返回承载PriceGraphFragment的HomeFragment。PriceGraphFragment是多次调用观察者的地方 我正在记录观察者发出的HashMap的hashcode,当我转到profile片段、弹出profile片段并返回price片段时,它显示了2个唯一的hashcode。这与我在旋转屏幕而不启动概要文件片段时从HashMap中看到的hashcode相反 实施Android 弹出片段后的多个LiveData观察者 问题,android,android-fragments,kotlin,android-navigation,android-livedata,Android,Android Fragments,Kotlin,Android Navigation,Android Livedata,摘要:导航到新片段、弹出新片段并返回原始片段后,片段中会触发多个LiveData观察者 详细信息:该体系结构由MainActivity组成,它承载一个HomeFragment,作为MainActivity的导航图中的起始目标。在HomeFragment中是一个通过编程方式膨胀的PriceGraphFragment。HomeFragment正在使用导航组件启动新的子片段ProfileFragment。按back键时,弹出ProfileFragment,应用程序返回承载PriceGraphFragm
view.setOnClickListener(Navigation.createNavigationClickListener(
R.id.action_homeFragment_to_profileFragment,null))
override-fun-onCreate(savedInstanceState:Bundle?){
super.onCreate(savedInstanceState)
priceViewModel=ViewModelProviders.of(this.get)(PriceDataViewModel::class.java)
}
priceViewModel.graphLiveData.observe(
观察者{priceGraphDataMap:HashMap?->
//这被多次调用。
})
priceViewModel=ViewModelProviders.of(this).get(PriceDataViewModel::class.java)
priceViewModel=ViewModelProviders.of(activity!!).get(PriceDataViewModel::class.java)
priceViewModel=ViewModelProviders.of(parentFragment!!).get(PriceDataViewModel::class.java)
中为生命周期所有者使用viewLifecycleOwner
而不是this
(@NonNull LifecycleOwner owner,@NonNull Observer这基本上是体系结构中的一个bug。您可以阅读更多关于它的信息。您可以使用getViewLifecycleOwner
来解决它,而不是在Observer
中使用它
像这样:
mViewModel.methodToObserve().observe(getViewLifecycleOwner(), new Observer<Type>() {
@Override
public void onChanged(@Nullable Type variable) {
mViewModel.methodToObserve().observe(getViewLifecycleOwner(),new Observer()){
@凌驾
公共void onChanged(@Nullable类型变量){
并将此代码放入onActivityCreated()
中,因为使用getViewLifecycleOwner
需要一个视图。首先,感谢所有在此发布的人。在过去5天中,您的建议和指针帮助我解决了此错误,因为涉及多个问题
解决的问题
在父片段(HomeFragment)中正确创建嵌套片段
之前:
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
if (savedInstanceState == null) {
fragmentManager
?.beginTransaction()
?.add(binding.priceDataContainer.id, PriceGraphFragment.newInstance())
?.commit()
fragmentManager
?.beginTransaction()
?.add(binding.contentFeedContainer.id, ContentFeedFragment.newInstance())
?.commit()
}
...
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
if (savedInstanceState == null
&& childFragmentManager.findFragmentByTag(PRICEGRAPH_FRAGMENT_TAG) == null
&& childFragmentManager.findFragmentByTag(CONTENTFEED_FRAGMENT_TAG) == null) {
childFragmentManager.beginTransaction()
.replace(priceDataContainer.id, PriceGraphFragment.newInstance(),
PRICEGRAPH_FRAGMENT_TAG)
.commit()
childFragmentManager.beginTransaction()
.replace(contentFeedContainer.id, ContentFeedFragment.newInstance(),
CONTENTFEED_FRAGMENT_TAG)
.commit()
}
...
}
之后:
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
if (savedInstanceState == null) {
fragmentManager
?.beginTransaction()
?.add(binding.priceDataContainer.id, PriceGraphFragment.newInstance())
?.commit()
fragmentManager
?.beginTransaction()
?.add(binding.contentFeedContainer.id, ContentFeedFragment.newInstance())
?.commit()
}
...
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
if (savedInstanceState == null
&& childFragmentManager.findFragmentByTag(PRICEGRAPH_FRAGMENT_TAG) == null
&& childFragmentManager.findFragmentByTag(CONTENTFEED_FRAGMENT_TAG) == null) {
childFragmentManager.beginTransaction()
.replace(priceDataContainer.id, PriceGraphFragment.newInstance(),
PRICEGRAPH_FRAGMENT_TAG)
.commit()
childFragmentManager.beginTransaction()
.replace(contentFeedContainer.id, ContentFeedFragment.newInstance(),
CONTENTFEED_FRAGMENT_TAG)
.commit()
}
...
}
在onCreate()
中创建ViewModels,而不是为父片段和子片段创建onCreateView()
正在初始化onCreate()
中的子片段(PriceFragment)的数据请求(Firebase Firestore查询)数据,而不是onViewCreated()
,但仅当saveInstanceState为null时,才会执行此操作
非因素
有人建议了几个项目,但结果证明对解决此错误没有影响
在onActivityCreated()
中创建观察者。我将我的观察者保存在子片段(PriceFragment)的onViewCreated()
中
在创建过程中使用viewLifecycleOwner
。我以前使用过子片段(PriceFragment)的这个。尽管viewLifecycleOwner
不会影响这个bug,但总体来说它似乎是最佳实践,所以我保留了这个新的实现
最好在onCreate
中初始化视图模型并观察实时数据对象
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
viewModel = ViewModelProvider(this).get(MyFragmentViewModel::class.java)
// 'viewLifecycleOwner' is not available here, so use 'this'
viewModel.myLiveData.observe(this) {
// Do something
}
}
但是,无论您在何处初始化视图模型,无论是在onCreate
还是onViewCreated
中,它都将为您提供相同的视图模型对象,因为它在片段的生命周期中只创建了一次
重要的部分是观察onCreate
中的实时数据。因为onCreate
仅在片段创建时调用,所以只能调用一次observe
onViewCreated
在创建片段时以及从后堆栈带回片段时(在将片段弹出到其顶部后)都被调用。如果在onViewCreated
中观察实时数据,它将在从后堆栈返回时立即从上一次调用中获取实时数据所保存的现有数据
相反,使用onViewCreated
仅获取数据