观察LiveData在创建碎片时被调用

3
简而言之,当观察器处于活动状态时,我执行通知操作时它能正常工作。但是,当我返回到先前的片段(使用导航组件)并再次导航到当前片段时,会创建一个新片段,并且由于某种原因,观察器被调用。
为什么在返回时观察器没有被删除呢?它应该根据片段的生命周期来运行。 我已经尝试在onStop中移除了它,但观察器仍然被调用。
更多细节: 我的每个项目片段都分为三部分:模型、viewModel和view。 在视图部分中,我首先设置了viewModel。
class EmergencyFragment : Fragment() {

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

在onViewCreated方法中,我设置了Observer对象,以便在LiveData中进行任何更改时,我会在此处收到更改通知:
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
   super.onViewCreated(view, savedInstanceState)
   emergencyFragmentViewModel.isEmergencyEventMediaLDSuccess.observe(viewLifecycleOwner, Observer {
       Log.d("sendEmergencyEvent", "isEmergencyEventMediaLDSuccess observer called")
       }
   })
}

在ViewModel类中,我将LiveData参数设置如下:
EmergencyFragmentViewModel: ViewModel() {
   var isEmergencyEventMediaLDSuccess: LiveData<Boolean> = MutableLiveData()
       private set
   private val observerEventMedia = Observer<Boolean> { (isEmergencyEventMediaLDSuccess as MutableLiveData).value = it}

在init中,我设置了一个观察者:
init {
   EmergencyFragmentModel.isEmergencyEventMediaLDSuccessModel.observeForever(observerEventMedia)
}

当然,需要时应该进行删除。
override fun onCleared() {
   super.onCleared()
   EmergencyFragmentModel.isEmergencyEventMediaLDSuccessModel.removeObserver(observerEventMedia)
}

模型的部分定义如下:
class EmergencyFragmentModel {
   companion object{
       val isEmergencyEventMediaLDSuccessModel: LiveData<Boolean> = MutableLiveData()

我发起网络请求,当有响应时发送通知。

override fun onResponse(call: Call<Int>, response: Response<Int>) {
   if(response.isSuccessful) {
       (isEmergencyEventLDModelSuccess as MutableLiveData).postValue(true)
       Log.d("succeed", "sendEmergencyEvent success: ${response.body().toString()}")
   }

有没有人知道我缺了什么?为什么当有一个活跃的Observe并且我回到之前的片段(我使用导航组件)并再次导航到当前片段时,会调用Observe?我可以理解当创建ViewModel实例并执行LiveData参数的setValue时,它会被通知。但是为什么当我返回时观察没有被移除?我尝试在onStop中移除观察,但它仍然发生。

override fun onStop() {
        super.onStop()
        emergencyFragmentViewModel.isEmergencyEventMediaLDSuccess.removeObservers(viewLifecycleOwner)
        emergencyFragmentViewModel.isEmergencyEventMediaLDSuccess.removeObserver(observeEmergencyEventLDSuccess)
    }

1
如果你回到片段,它的视图会被重新创建,并且新的观察者也会被创建。然后,该观察者会被“提升”到LiveData的当前状态/值 - 这是按设计来的。 - Pawel
3个回答

1
@Pawel是正确的。LiveData 存储值,每次观察它(在此情况下,在您的onViewCreated中),它将发出存储的最后一个值。
也许你想要类似于SingleLiveEvent的东西,它在有人读取它后清除其值。
因此,当你来回切换时,它不会发出那个上次被清除的值。

0
我通过在 Kotlin 中检查生命周期状态创建了一个扩展来解决这个问题。
fun <T> LiveData<T>.observeOnResumedState(viewLifecycleOwner: LifecycleOwner, observer: Observer<T>) {
    this.observe(viewLifecycleOwner) {
        if (viewLifecycleOwner.lifecycle.currentState == Lifecycle.State.RESUMED) {
            observer.onChanged(it)
        }
    }
}

而这是我观察的方式

viewModel.result.observeOnResumedState(viewLifecycleOwner) {
    // TODO
}

0

根据我的理解,您只想在新值与旧值不同时运行观察者。这可以通过在viewModel中保留另一个变量中的值来实现。

    if (newValue == viewModel.retainedValue) return@observe
    viewModel.retainedValue = newValue

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接