I have a livedata object that I call on my fragment. First time works fine, it only tiggers just one time, but second time I enter the fragment it triggers twice and don't understand why.
This is where I call the observe:
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) }
}
And this is the method in my view model:
val videosData = MutableLiveData<List<DtoCelebrityResource>>()
fun getVideosData() {
showLoader()
trainingWithFamousUseCase
.build(this)
.executeWithError({
videosData.value = it
hideLoader()
}, {
hideLoader()
})
}
CodePudding user response:
Whenever your fragment is created, you run this:
viewModel.getVideosData()
viewModel.videosData.observe(viewLifecycleOwner, Observer {
//second time I enter the fragment it triggers his twice
videoCategoryAdapter.loadItems(it)
})
I'm assuming getVideosData is some async operation that fetches data from a database or something, in another coroutine/thread. In that case, when that method updates the LiveData with videosData.value = it, it will be sometime later
The next line is where you observe the LiveData - if it currently has a value, it will be delivered immediately, and the lambda will get run. When getVideosData finishes and sets a value, the observer will run again.
The reason you're not seeing this the first time is probably because your LiveData doesn't have an initial value (val videosData = MutableLiveData<List<DtoCelebrityResource>>()) so when you first observe it, the lambda doesn't fire. Then when the video data is set, you get the callback, so it only happens once.
But because that LiveData now has some data, and the point of a ViewModel is to maintain state when things like Fragments and Activities are closed, next time you open that fragment videosData does have an initial value when you first call observe. So you see that, and the update.
There are a bunch of ways you could approach this, but calling distinctUntilChanged() on videosData (which creates a LiveData that only pushes updates when the data has "changed") might be enough to solve it. e.g.
val videosData = MutableLiveData<List<DtoCelebrityResource>>().distinctUntilChanged()
CodePudding user response:
try
viewModel.videosData.observe(viewLifecycleOwner, Observer {
if(getViewLifecycleOwner().getLifecycle().getCurrentState()== Lifecycle.State.RESUMED){
videoCategoryAdapter.loadItems(it)
}
})
