在 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>>`
}
}
}
}
该应用程序的基本思想如下:每当服务器启动时使用改造从服务器获取数据,当服务器无法访问时回退到本地房间数据库。但是,我在视图模型中保存数据的方式有问题。我对从 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>>`
}
}
}
}