kotlin 为什么livedata observe触发了两次?

2cmtqfgy  于 2023-06-24  发布在  Kotlin
关注(0)|答案(2)|浏览(570)

我有一个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()
        })
}
c0vxltue

c0vxltue1#

每当你的片段被创建时,你运行这个:

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时,它将 * 稍后 *
下一行是你observe LiveData的地方--如果它当前有一个值,它将被立即交付,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()
zzoitvuj

zzoitvuj2#

将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) }
}

相关问题