【问题标题】:Syncing data fetched from retrofit (MutableLiveData) with data from Room DB (LiveData) in an android app在 Android 应用程序中将从改造 (MutableLiveData) 获取的数据与来自 Room DB (LiveData) 的数据同步
【发布时间】:2021-04-15 15:52:09
【问题描述】:

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

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

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

也无法使 DAO 返回 MutableLiveData&lt;List&lt;Ingredient&gt;&gt;(出现一些编译错误)。而且我听说尝试将其中一种类型转换为另一种并不是最佳实践。所以我不确定我还能尝试什么。

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>>`
            }
        }
    }

【问题讨论】:

    标签: kotlin retrofit android-room


    【解决方案1】:

    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>>`
                }
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-04-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-07-20
      相关资源
      最近更新 更多