Mar*_*ean 1 android mvvm kotlin android-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) }
}
Run Code Online (Sandbox Code Playgroud)
这是我的视图模型中的方法:
val videosData = MutableLiveData<List<DtoCelebrityResource>>()
fun getVideosData() {
showLoader()
trainingWithFamousUseCase
.build(this)
.executeWithError({
videosData.value = it
hideLoader()
}, {
hideLoader()
})
}
Run Code Online (Sandbox Code Playgroud)
每当创建片段时,您都可以运行以下命令:
viewModel.getVideosData()
viewModel.videosData.observe(viewLifecycleOwner, Observer {
//second time I enter the fragment it triggers his twice
videoCategoryAdapter.loadItems(it)
})
Run Code Online (Sandbox Code Playgroud)
我假设getVideosData是一些异步操作,在另一个协程/线程中从数据库或其他东西中获取数据。在这种情况下,当该方法更新LiveDatawith时videosData.value = it,它将是稍后
下一行是 LiveData 的位置observe- 如果它当前有一个值,它将立即传递,并且 lambda 将运行。当getVideosData完成并设置一个值时,观察者将再次运行。
您第一次没有看到这一点的原因可能是因为您LiveData没有初始值(val videosData = MutableLiveData<List<DtoCelebrityResource>>()),所以当您第一次observe它时,lambda 不会触发。然后,当设置视频数据时,您会收到回调,因此只会发生一次。
但是因为 LiveData 现在有一些数据,并且 a 的目的ViewModel是在关闭 Fragments 和 Activity 等内容时保持状态,所以下次打开该 Fragment 时,当您第一次调用时,它videosData 确实有一个初始值observe。所以你看到了,还有更新。
有很多方法可以解决这个问题,但是调用distinctUntilChanged()(videosData创建一个 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()
Run Code Online (Sandbox Code Playgroud)