Android,如何从同一个 ViewModel 中观察 LiveData
Android, how to observe LiveData from within the same ViewModel
在 LiveData 和 MVVM 架构方面,我完全是个新手。我试图弄清楚如何观察 ViewModel 中的 LiveData 以根据它是否为空来更新另一个变量。
我正在从我的 Room 数据库中获取 LiveData:
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() }
我希望 ViewModel 中的另一个变量 private val empty: Boolean
在列表返回为空 (null) 时更新。这将用于将 Fragment 中的 ImageView 从 Visible.GONE 更新为 Visible.VISIBLE。
如何同步检查val meals
是否为空?
我看过一些人说要使用observeForever
,但架构指南明确建议不要在 ViewModels 中使用任何观察者。
我可能可以在 Fragment 中观察 LiveData,但这需要 Fragment 中的业务逻辑,即:
viewModel.meals.observe(viewLifecycleOwner) {
if meals.value.isEmpty() imageView.visibility = View.VISIBLE else imageView.visibility = View.GONE
}
而且我希望 Fragment 尽可能保持 'dumb',因此我更愿意在 ViewModel 中包含该逻辑。这可能吗?
我不知道你的代码是如何设置的,但你可以像下面那样做
向 ViewModel 添加变量
val empty = MutableLiveData<Boolean>()
在meals
观察者
viewModel.meals.observe(viewLifecycleOwner) {
viewModel.empty,postValue(meals.value.isEmpty())
然后观察empty
使用 MediatorLiveData
在您的 ViewModel class 中,创建
val empty = MediatorLiveData<Boolean>()
然后
empty.addSource(meals) {
empty.value = it.isEmpty()
}
您可以检查实时数据 meal
以查看它是否为空或为空,然后使用您的实时数据 empty
触发,如下所示:
在视图模型中,您创建了一个实时数据 isEmptyMeals
。此实时数据变量将始终在 meals
值更改时触发,并将检查您的 meals
值是否为空或 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()
}
}
并且在该片段中,您将收听观察实时数据 isEmptyMeals
并执行隐藏或显示您想要的图像视图的逻辑。
Fragment.kt
viewModel.isEmptyMeals.observe(viewLifecycleOwner) {
imageView.visibility = if (it) View.VISIBLE else View.GONE
}
在 LiveData 和 MVVM 架构方面,我完全是个新手。我试图弄清楚如何观察 ViewModel 中的 LiveData 以根据它是否为空来更新另一个变量。
我正在从我的 Room 数据库中获取 LiveData:
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() }
我希望 ViewModel 中的另一个变量 private val empty: Boolean
在列表返回为空 (null) 时更新。这将用于将 Fragment 中的 ImageView 从 Visible.GONE 更新为 Visible.VISIBLE。
如何同步检查val meals
是否为空?
我看过一些人说要使用observeForever
,但架构指南明确建议不要在 ViewModels 中使用任何观察者。
我可能可以在 Fragment 中观察 LiveData,但这需要 Fragment 中的业务逻辑,即:
viewModel.meals.observe(viewLifecycleOwner) {
if meals.value.isEmpty() imageView.visibility = View.VISIBLE else imageView.visibility = View.GONE
}
而且我希望 Fragment 尽可能保持 'dumb',因此我更愿意在 ViewModel 中包含该逻辑。这可能吗?
我不知道你的代码是如何设置的,但你可以像下面那样做
向 ViewModel 添加变量
val empty = MutableLiveData<Boolean>()
在meals
观察者
viewModel.meals.observe(viewLifecycleOwner) {
viewModel.empty,postValue(meals.value.isEmpty())
然后观察empty
使用 MediatorLiveData
在您的 ViewModel class 中,创建
val empty = MediatorLiveData<Boolean>()
然后
empty.addSource(meals) {
empty.value = it.isEmpty()
}
您可以检查实时数据 meal
以查看它是否为空或为空,然后使用您的实时数据 empty
触发,如下所示:
在视图模型中,您创建了一个实时数据 isEmptyMeals
。此实时数据变量将始终在 meals
值更改时触发,并将检查您的 meals
值是否为空或 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()
}
}
并且在该片段中,您将收听观察实时数据 isEmptyMeals
并执行隐藏或显示您想要的图像视图的逻辑。
Fragment.kt
viewModel.isEmptyMeals.observe(viewLifecycleOwner) {
imageView.visibility = if (it) View.VISIBLE else View.GONE
}