为什么livedata观察被触发两次



我有一个在片段上调用的livedata对象。第一次很好,它只会触发一次,但第二次我进入片段时,它会触发两次,不明白为什么。

这就是我称之为观察者的地方:

override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
return inflater.inflate(R.layout.activity_train_with_famous_detail, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
setupUi(view)
(activity as TrainingWithFamousActivity).hideToolbar()
setupListCategoryVideos(view)
viewModel.getVideosData()
viewModel.videosData.observe(viewLifecycleOwner, Observer {
//second time I enter the fragment it triggers his twice
videoCategoryAdapter.loadItems(it)
})
viewModel.videoSelected?.let { loadTrainWithFamousDetailsData(it) }
}

这就是我的视图模型中的方法:

val videosData = MutableLiveData<List<DtoCelebrityResource>>()
fun getVideosData() {
showLoader()
trainingWithFamousUseCase
.build(this)
.executeWithError({
videosData.value = it
hideLoader()
}, {
hideLoader()
})
}

每当创建片段时,都会运行以下命令:

viewModel.getVideosData()
viewModel.videosData.observe(viewLifecycleOwner, Observer {
//second time I enter the fragment it triggers his twice
videoCategoryAdapter.loadItems(it)
})

我假设getVideosData是某种异步操作,它在另一个协程/线程中从数据库或其他地方获取数据。在这种情况下,当该方法用videosData.value = it更新LiveData时,它将在稍后

下一行是observeLiveData的位置——如果它当前有一个值,它将立即传递,lambda将运行。当getVideosData完成并设置值时,观察者将再次运行


你第一次没有看到这个可能是因为你的LiveData没有初始值(val videosData = MutableLiveData<List<DtoCelebrityResource>>()(,所以当你第一次observe时,lambda不会激发。然后,当设置视频数据时,您会得到回调,所以它只发生一次。

但是,因为LiveData现在有一些数据,而ViewModel的目的是在Fragments和Activities之类的东西关闭时保持状态,所以下次打开该片段时,videosData在第一次调用observe时是否有初始值。所以你看到了,以及更新。

有很多方法可以解决这个问题,但在videosData上调用distinctUntilChanged()(它创建一个LiveData,只在数据根据其equals函数"更改"时推送更新(可能足以解决这个问题。例如

// internal mutable version
private val _videosData = MutableLiveData<List<DtoCelebrityResource>>()
// exposed immutable version, with the "emit distinct values" transformation
val videosData: LiveData<List<DtoCelebrityResource>> = _videosData.distinctUntilChanged()

将viewModel放入onCreate((方法中并使用savedInstanceState

...
lateinit var model:/*ViewModelClass*/
...
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
viewModel=ViewModelProvider(this)[/*ViewModel*/::class.java]
if (savedInstanceState==null){
viewModel.getVideosData()
}
}
override fun onSaveInstanceState(outState: Bundle) {
outState.putString("value","value")
super.onSaveInstanceState(outState)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
setupUi(view)
(activity as TrainingWithFamousActivity).hideToolbar()
setupListCategoryVideos(view)
//remove viewModel.getVideosData()
viewModel.videosData.observe(viewLifecycleOwner, Observer {

videoCategoryAdapter.loadItems(it)
})
viewModel.videoSelected?.let { loadTrainWithFamousDetailsData(it) }
}

最新更新