即使使用viewLifecycleOwner,LiveData观察器也会触发两次

时间:2019-08-09 16:05:09

标签: android kotlin android-lifecycle android-livedata observers

我正在与一个LiveData观察器挣扎,后者会触发两次。在我的片段中,我观察到一个LiveData,如下所示,将viewLifeCycleOwner用作LifeCycleOwner

private lateinit var retailViewModel: RetailsViewModel

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

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {

  retailViewModel.retailLiveData.observe(viewLifecycleOwner, Observer {
    // updating UI here, but firing twice!
  }

  retailViewModel.getRetailById(retail.id)
} 

这是我的视图模型:

class RetailsViewModel(override val service: MyFoodyApiService = MyFoodyApiService.service) :
    BaseViewModel(service) {

    var retailLiveData: MutableLiveData<Retail> = MutableLiveData()

    fun getRetailById(id: Int) {
        scope.launch {
            try {
                val response =
                    service.getRetailById(authString, id).await()
                when (response.isSuccessful) {
                    true -> {
                        response.body()?.let { payload ->
                            retailLiveData.postValue(payload.data)
                        } ?: run {
                            errorLiveData.postValue("An error occurred: ${response.message()}")
                        }
                    }
                    false -> errorLiveData.postValue("An error occurred: ${response.message()}")
                }
            } catch (e: Exception) {
                noConnectionLiveData.postValue(true)
            }
        }
    }

}

当我第一次运行该片段时,一切正常,但是当我转到其DetailFragment并返回时,retailLiveData观察者回调被触发两次。根据{{​​3}}的介绍,这是一个已知问题,通过引入viewLifeCycleOwner解决了这一问题,一旦片段的视图被破坏,它应该有助于删除活动的观察者,但是对于我来说似乎没有帮助。

1 个答案:

答案 0 :(得分:2)

之所以发生这种情况,是因为当您打开另一个片段时,视图模型会保留值,但是该片段的视图被破坏了。当您回到片段时,将重新创建视图,并订阅 testPost(req: any, res: any) { let { name, first_last_name, second_last_name, username, password, mail, phone, cellphone, history } = req.body; let newClient = new Client({ name, first_last_name, second_last_name, username, password, mail, phone, cellphone, history:[] }); newClient.save((error, client) => { if (error) return res.status(500).send({ message: `Error: ${error}` }); res.status(200).send({ message: `Client ${client.name} saved` }); }); ,该变量仍保留先前的值,并在片段移至开始状态时立即通知您的观察者。但是您正在retailLiveData中调用retailViewModel.getRetailById(retail.id),因此一段时间后,值将更新,并再次通知观察者。

一种可能的解决方案是从视图模型的onViewCreated方法调用getRetailById(),然后将结果缓存到视图模型的生存期中。