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
}