Reputation: 75
I'm a complete novice when it comes to LiveData and MVVM architecture. I'm trying to figure out how to observe a LiveData<List> in the ViewModel to update another variable depending on if it is empty or not.
I'm getting the LiveData from my Room database with this:
class MealsViewModel @Inject constructor(
private val mealDao : MealDao
) : ViewModel() {
...
private val currentDay: MutableLiveData<Date> = MutableLiveData(Date())
val meals = Transformations.switchMap(currentDay){ date -> mealDao.getMeals(date).asLiveData() }
I would like for another variable in the ViewModel, private val empty: Boolean
, to update anytime the list is returned empty (null). This will be used in updating an ImageView in the Fragment from Visible.GONE to Visible.VISIBLE.
How do I check if val meals
is empty synchronously?
I've read around and saw some people said to useobserveForever
, but the architecture guide explicitly advises against any observers in ViewModels.
I could probably observe the LiveData in the Fragment, but that would require business logic in the Fragment, ie:
viewModel.meals.observe(viewLifecycleOwner) {
if meals.value.isEmpty() imageView.visibility = View.VISIBLE else imageView.visibility = View.GONE
}
And I'd like to keep the Fragment as 'dumb' as possible, so I'd prefer to have that logic in the ViewModel. Is that possible?
Upvotes: 0
Views: 6903
Reputation: 1324
I don't know exactly how your code is set up but you can do something like below
Add variable to ViewModel
val empty = MutableLiveData<Boolean>()
In meals
observer
viewModel.meals.observe(viewLifecycleOwner) {
viewModel.empty,postValue(meals.value.isEmpty())
Then observe from empty
Using MediatorLiveData
In your ViewModel class, create
val empty = MediatorLiveData<Boolean>()
Then
empty.addSource(meals) {
empty.value = it.isEmpty()
}
Upvotes: 0
Reputation: 2421
You can check live data meal
to see if it's empty or null and then trigger with your live data empty
like this:
In the viewmodel, you create a livedata isEmptyMeals
. This live data variable will always trigger when meals
value change and will check if your meals
value are empty or null.
MealsViewModel.kt
class MealsViewModel @Inject constructor(
private val mealDao : MealDao
) : ViewModel() {
...
private val currentDay: MutableLiveData<Date> = MutableLiveData(Date())
val meals = Transformations.switchMap(currentDay){ date -> mealDao.getMeals(date).asLiveData() }
val isEmptyMeals = meals.map {
it.isNullOrEmpty()
}
}
And in the fragment, you will listen to observe the livedata isEmptyMeals
and perform the logic to hide or show the image view you want.
Fragment.kt
viewModel.isEmptyMeals.observe(viewLifecycleOwner) {
imageView.visibility = if (it) View.VISIBLE else View.GONE
}
Upvotes: 1