在 android 应用程序中同步从改造 (MutableLiveData) 获取的数据与来自 Room DB (LiveData) 的数据

Syncing data fetched from retrofit (MutableLiveData) with data from Room DB (LiveData) in an android app

该应用程序的基本思想如下:每当服务器启动时使用改造从服务器获取数据,当服务器无法访问时回退到本地房间数据库。但是,我在视图模型中保存数据的方式有问题。我对从 Room 获取的数据使用 LiveData,对从服务器获取的数据使用 MutableLiveData。虽然不确定如何获得单一数据源。 Retrofit API return 将我的实体 (Recipe) 作为 List<Recipe>。我知道坚持使用 MutableLiveData:

的唯一方法
var readAllIngredients = MutableLiveData<List<Ingredient>>().apply { value = emptyList() }
...
readAllIngredients.postValue(NetworkService.service.getIngredients())

readAllIngredients 更改为 LiveData<List<Ingredient>> 然后尝试设置列表的 value 字段不起作用,因为显然 value 不可分配给。

也无法创建 DAO return MutableLiveData<List<Ingredient>>(出现一些编译错误)。我听说尝试将其中一种类型转换为另一种类型并不是最佳做法。所以我不确定我还能尝试什么。

class InventoryViewModel(application: Application): AndroidViewModel(application) {
    var readAllIngredients = MutableLiveData<List<Ingredient>>().apply { value = emptyList() }
    private val ingredientRepository: IngredientRepository

    init {
        val ingredientDAO = ShoppingAppDatabase.getDatabase(application).ingredientDAO()
        ingredientRepository = IngredientRepository(ingredientDAO)
        viewModelScope.launch(Dispatchers.IO) {
            // logic moved from repository in order to make example more concise 
            if(NetworkService.serverReachable()) {
                readAllIngredients.postValue(NetworkService.service.getIngredients())
            }
            else {
                //save the data from the database somehow; used to do it like
                //readAllIngredients = ingredientRepository.allIngredients 
                //when readAllIngredients was of type `LiveData<List<Ingredient>>`
            }
        }
    }

MediatorLiveData 用于合并多个源。示例:

class InventoryViewModel(application: Application): AndroidViewModel(application) {
    var readAllIngredients = MediatorLiveData<List<Ingredient>>().apply { value = emptyList() }
    private val ingredientRepository: IngredientRepository
    private var gotNetworkIngredients = false

    init {
        val ingredientDAO = ShoppingAppDatabase.getDatabase(application).ingredientDAO()
        ingredientRepository = IngredientRepository(ingredientDAO)
        readAllIngredients.addSource(ingredientRepository.allIngredients) { repoValue ->
            if (!gotNetworkIngredients) {
                readAllIngredients.value = repoValue
            }
        }

        viewModelScope.launch(Dispatchers.IO) {
            // logic moved from repository in order to make example more concise 
            if(NetworkService.serverReachable()) {
                gotNetworkIngredients = true
                readAllIngredients.postValue(NetworkService.service.getIngredients())
            }
            else {
                //save the data from the database somehow; used to do it like
                //readAllIngredients = ingredientRepository.allIngredients 
                //when readAllIngredients was of type `LiveData<List<Ingredient>>`
            }
        }
    }
}