使用带有参数(MVVM、存储库)的firestore查询更新android livedata
我想用MVVM模型实现一个android应用程序。问题是我找不到一种方法来使用包含参数的Firestore调用更新ViewModel中的数据。repository类负责加载数据,这些数据要么从本地房间数据库(works)获取,要么从firestore获取 我的问题: 我的实现正确吗?从房间数据库获取数据是可行的。但是从Firestore加载数据不起作用。我认为问题在于,当FirestoreFoodWebservice类中的getFoods函数返回时,firestore查询尚未执行。我能做些什么来解决这个问题 我的架构如下所示:使用带有参数(MVVM、存储库)的firestore查询更新android livedata,android,mvvm,google-cloud-firestore,android-livedata,Android,Mvvm,Google Cloud Firestore,Android Livedata,我想用MVVM模型实现一个android应用程序。问题是我找不到一种方法来使用包含参数的Firestore调用更新ViewModel中的数据。repository类负责加载数据,这些数据要么从本地房间数据库(works)获取,要么从firestore获取 我的问题: 我的实现正确吗?从房间数据库获取数据是可行的。但是从Firestore加载数据不起作用。我认为问题在于,当FirestoreFoodWebservice类中的getFoods函数返回时,firestore查询尚未执行。我能做些什么来
MainActivity -> MainActivitiyViewModel -> FoodRepository ->
(
if (data is in room database) return from database
else (get data from firestore webservice)
)
主要活动:
mainActivityViewModel = ViewModelProviders.of(this).get(MainActivityViewModel::class.java)
mainActivityViewModel.getFoodsFilteredByName().observe(this, Observer { foods ->
run {
searchResultAdapter.setData(foods)
progressIndicator.visibility = View.INVISIBLE
}
})
SearchResultAdapter:
fun setData(foods : List<Food>) {
if (searchResult.isEmpty()) {
searchResult = ArrayList(foods);
notifyItemRangeInserted(0, searchResult.size)
return
}
val result = DiffUtil.calculateDiff(object : DiffUtil.Callback() {
override fun getOldListSize(): Int {
return searchResult.size
}
override fun getNewListSize(): Int {
return foods.size
}
override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
return searchResult[oldItemPosition].foodName === foods[newItemPosition].foodName
}
override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
val newFood = foods[newItemPosition]
val oldFood = searchResult[oldItemPosition]
return newFood == oldFood
}
})
searchResult = ArrayList(foods)
result.dispatchUpdatesTo(this)
}
fun setData(食品:列表){
if(searchResult.isEmpty()){
searchResult=ArrayList(食品);
notifyItemRangeInserted(0,searchResult.size)
返回
}
val result=DiffUtil.calculateDiff(对象:DiffUtil.Callback(){
重写getOldListSize():Int{
返回searchResult.size
}
重写getNewListSize():Int{
返回食物。大小
}
覆盖乐趣项相同(oldItemPosition:Int,newItemPosition:Int):布尔值{
返回搜索结果[oldItemPosition]。foodName===foods[newItemPosition]。foodName
}
覆盖相同的内容(oldItemPosition:Int,newItemPosition:Int):布尔值{
val newFood=食品[newItemPosition]
val oldFood=搜索结果[oldItemPosition]
返回新食品==旧食品
}
})
searchResult=ArrayList(食品)
结果。dispatchUpdatesTo(此)
}
MainActivityViewModel:
private val foodsFilteredByName: LiveData<List<Food>>
private val filterName = MutableLiveData<String>()
init {
val foodsDao = FoodRoomDatabase.getDatabase(application, viewModelScope).foodDao()
val webservice = FirestoreFoodWebservice()
repository = FoodRepository(foodsDao, webservice)
foodsFilteredByName = Transformations.switchMap(filterName) { c -> repository.getFoods(c) }
}
...
fun setFilter(name: String ) {
filterName.value = name
}
private val foodsFilteredByName:LiveData
private val filterName=MutableLiveData()
初始化{
val foodsDao=FoodRoomDatabase.getDatabase(应用程序,viewModelScope).foodDao()
val webservice=FirestoreFoodWebservice()
repository=FoodRepository(foodsDao、webservice)
foodsFilteredByName=Transformations.switchMap(filterName){c->repository.getFoods(c)}
}
...
fun setFilter(名称:String){
filterName.value=名称
}
食品储备:
fun getFoods(foodName: String): MutableLiveData<List<Food>> {
// if data exists in room database return the data
// else:
var foods: List<Food> = webservice.getFoods(foodName)
val data = MutableLiveData<List<Food>>()
data.value = foods
return data
}
fun-getFoods(foodName:String):MutableLiveData{
//如果房间数据库中存在数据,则返回数据
//其他:
var foods:List=webservice.getFoods(foodName)
val data=MutableLiveData()
data.value=食品
返回数据
}
FirestoreFoodWebservice:
(在切换到MVVM之前,我在MainActivity中进行了查询。在那里查询工作正常。)
fun-getFoods(foodName:String):列表{
val query=//创建firestore查询
query.get().addOnSuccessListener{result->
用于(结果中的文档){
食品
//用结果中的数据填充食物
食物。添加(食物)
}
}.addOnFailureListener{/*ToDo:实现*/}
返回食物
//编辑:将foodNames更改为foods
}
正如您所建议的,问题在于FirestoreFoodWebservice#getFoods
在firestore查询返回之前返回。您可以通过(1)使getFoods
等待查询返回,(2)使getFoods
使用回调返回查询结果,或(3)使getFoods
返回LiveData
实例来解决此问题。无法决定哪一个更好,因为您的代码中似乎有另一个关于房间的问题。通常,您不应该能够同步地判断数据库中是否存在某些数据。请提供完整的FoodRepository#getFoods
code.@SanlokLee谢谢。(3) 现在可以工作了。您是对的,从文件室同步加载数据不起作用。getFoods方法尚未完全实现。经过一些研究,我现在发现我的实现违反了“单一真相来源”原则。如果你把你的评论作为答案发表,我会把它标记为正确。当实现工作时,我会发布一个答案。问题是,正如您所建议的,FirestoreFoodWebservice#getFoods
在firestore查询返回之前返回。您可以通过(1)使getFoods
等待查询返回,(2)使getFoods
使用回调返回查询结果,或(3)使getFoods
返回LiveData
实例来解决此问题。无法决定哪一个更好,因为您的代码中似乎有另一个关于房间的问题。通常,您不应该能够同步地判断数据库中是否存在某些数据。请提供完整的FoodRepository#getFoods
code.@SanlokLee谢谢。(3) 现在可以工作了。您是对的,从文件室同步加载数据不起作用。getFoods方法尚未完全实现。经过一些研究,我现在发现我的实现违反了“单一真相来源”原则。如果你把你的评论作为答案发表,我会把它标记为正确。我会在实现成功后发布一个答案。
fun getFoods(foodName: String): List<Food> {
val query = // create firestore query
query.get().addOnSuccessListener { result ->
for (document in result) {
var food = Food()
// fill food with data from result
foods.add(food)
}
}.addOnFailureListener { /* ToDo: Implement */ }
return foods
// Edit: Changed foodNames to foods
}