LiveData 观察者永远不会在共享 ViewModel 之间被删除

问题描述 投票:0回答:1

我快要疯了。

我有一个在FragmentA和FragmentB之间共享的SharedViewModel,其中包含一个LiveData:

class SharedViewModel : ViewModel() {

    private val _searchParameters = MutableLiveData(SearchParameters())
    val searchParameters: LiveData<SearchParameters> = _searchParameters
}

我在 FragmentA 的 onViewCreated() 中观察到这个 liveData(仅在 FragmentB 中没有):

viewModel.searchParameters.observe(viewLifecycleOwner) { searchAndFilter ->
   Log.d("FragmentA", "observed searchParameters in FragmentA")
   mSearchAdapter.updateSearchParameters(searchAndFilter)
}

我的问题是当 FragmentA 被销毁时,观察者永远不会被删除:

如果我导航到 FragmentB (使用导航组件),然后从 FragmentB 执行 findNavController().popBackStack(),我希望 FragmentA 删除我在

onDestroyView()
中的观察者(我已确认在导航到 FragmentB 时正确调用了该观察者) )。但这并没有发生。因此,当我导航回 FragmentA 时,会再次观察 LiveData,现在我对此 LiveData 进行了多次观察。如果我来回导航 10 次,我的观察者现在已被注册 10 次,并且每个事件都会被称为 10 次敌人。

我还尝试通过保留对观察者的引用并执行操作来手动删除观察者

override fun onDestroyView() {
     super.onDestroyView()

     Log.d("FragmentA", "onDestroyView")
     viewModel.searchParameters.removeObserver(searchParametersObserver)
}

但是同样的问题出现了。

所以我的问题是发生了什么事,我该如何解决这个问题?

android kotlin android-livedata
1个回答
0
投票

LiveData 观察者在 FragmentA 被销毁时没有被正确删除的问题可能源于观察者的注册和注销方式。在提供的代码片段中,观察者是在片段 A 的 onViewCreated() 方法中使用 viewLifecycleOwner 注册的,这是正确的方法。但是,在片段 A 的 onDestroyView() 方法中,尝试删除观察者可能不会有效,因为它引用了 searchParametersObserver,而所提供的代码中未定义该值。

要解决此问题,请确保使用与注册观察者相同的引用正确删除观察者。修改Fragment A的onDestroyView()方法中的代码,使用viewLifecycleOwner删除观察者。这是更正后的代码片段:

// In FragmentA onDestroyView()
override fun onDestroyView() {
    super.onDestroyView()

    Log.d("FragmentA", "onDestroyView")
    viewModel.searchParameters.removeObservers(viewLifecycleOwner)
}

此修改可确保当 Fragment A 的视图被销毁时,观察者也会被移除,从而防止观察者的多次注册以及在 Fragment A 和 Fragment B 之间来回导航时出现的后续问题。

© www.soinside.com 2019 - 2024. All rights reserved.