英文:
Koltin Flow is repeating execution using flatMapMerge
问题
以下是您提供的内容的翻译:
我试图实现一种从两个数据源(Room和FirebaseFirestore)获取产品的方法,使用Flows。
一切都很顺利,直到我注意到调试器无限返回到相同的断点。当“ViewmMdel.insertProducts(products)”的执行结束时,调试器会返回到Repository.getProducts(//)并重复。
我改变了方法,只使用暂停函数、协程,一切都很顺利,但我对如何使用Flows来实现这个方法感到好奇。
也许只是flatMapMerge处于预览版本。
提前感谢:D
以下是实现部分的翻译:
ViewModel:
fun getProductNames(companyName: String) {
viewModelScope.launch {
repository.getProducts(companyName).catch {
_event.value = AddSaleEvents.ShouldShowLoading(false)
_event.value = AddSaleEvents.ProductsFailureResponse(it.message.toString())
}.collect { products ->
productsList = products
if (products != emptyList<Product>()) {
_event.value = AddSaleEvents.ShouldShowLoading(false)
_event.value = AddSaleEvents.ProductsSuccessfulResponse(products)
insertProducts(products)
} else {
_event.value = AddSaleEvents.ShouldShowLoading(false)
_event.value = AddSaleEvents.ProductsSuccessfulResponse(products)
}
}
}
}
Repository:
@OptIn(FlowPreview::class)
override suspend fun getProducts(companyName: String): Flow<List<Product>> {
return localDataSource.getProducts().flatMapMerge { list ->
getProductsFromFirebase(list, companyName)
}.flowOn(Dispatchers.IO).catch {
Log.d("Error", it.message.toString())
}
}
private fun getProductsFromFirebase(products: List<Product>, companyName: String) = flow {
if (products.isEmpty()) {
remoteDataSource.getProducts(companyName).collect {
emit(it)
}
} else {
emit(products)
}
}
LocalDataSource with Room:
override suspend fun getProducts(): Flow<List<Product>> = saleDao.getProducts()
Firebase Data Source:
override suspend fun getProducts(company: String): Flow<List<Product>> = flow {
val response = fireStore.collection("products").whereEqualTo("company", company).get()
response.await()
if (response.isSuccessful && !response.result.isEmpty) {
emit(response.result.toObjects(FirebaseProduct::class.java).toEntity())
}
}.catch {
Log.d("Error", it.message.toString())
}
如何将一个流的响应链接到触发MVVM体系结构和干净架构中的另一个流?
如果可能的话,我想理解代码无限重复的原因。
英文:
I was trying to implement an approach to fetch products from two Data sources (Room & FirebaseFirestore) using Flows.
It was working fine until I noticed that the debugger was returning to the same break point infinitely. When the execution of "ViewmMdel.insertProducts(products)" ends, the debugger returns to Repository.getProducts(//) & repeats.
I changed the approach using only suspending functions & coroutines & works fine but I am curious about how I must to use Flows to implement this approach.
Maybe is only that flatMapMerge is in preview version.
Thanks in advance
This one is the implementation:
ViewModel:
fun getProductNames(companyName: String) {
viewModelScope.launch {
repository.getProducts(companyName).catch {
_event.value = AddSaleEvents.ShouldShowLoading(false)
_event.value = AddSaleEvents.ProductsFailureResponse(it.message.toString())
}.collect { products ->
productsList = products
if (products != emptyList<Product>()) {
_event.value = AddSaleEvents.ShouldShowLoading(false)
_event.value = AddSaleEvents.ProductsSuccessfulResponse(products)
insertProducts(products)
} else {
_event.value = AddSaleEvents.ShouldShowLoading(false)
_event.value = AddSaleEvents.ProductsSuccessfulResponse(products)
}
}
}
}
Repository:
@OptIn(FlowPreview::class)
override suspend fun getProducts(compnayName: String): Flow<List<Product>> {
return localDataSource.getProducts().flatMapMerge { list -> // LINE RUNNING INFINITELY
getProductsFromFirebase(list, compnayName)
}.flowOn(Dispatchers.IO).catch {
Log.d("Error", it.message.toString())
}
}
private fun getProductsFromFirebase(products: List<Product>, compnayName: String) = flow {
if (products.isEmpty()) {
remoteDataSource.getProducts(compnayName).collect {
emit(it)
}
} else {
emit(products)
}
}
LocalDataSource with Room:
override suspend fun getProducts(): Flow<List<Product>> = saleDao.getProducts()
Firebase Data Source:
override suspend fun getProducts(company: String): Flow<List<Product>> = flow {
val response = fireStore.collection("products").whereEqualTo("company", company).get()
response.await()
if (response.isSuccessful && !response.result.isEmpty) {
emit(response.result.toObjects(FirebaseProduct::class.java).toEntity())
}
}.catch {
Log.d("Error", it.message.toString())
}
How can I chain the response of a flow to trigger another one inside the MVVM Architecture + Clean Architecture?
6 if it is possible, I want to understand the reason the code is repeating infinitely.
答案1
得分: 0
看起来insertProducts(products)
触发了room的DAO。
所以localDataSource.getProducts()
是一个可观察的读取查询。
可观察查询是读取操作,每当查询引用的任何表发生更改时,都会发出新的值。
尝试更改LocalDataSource
interface SaleDao {
// fun getProducts(): Flow<List<Product>>
suspend fun getProducts(): List<Product>
}
英文:
Looks like insertProducts(products)
triggers room's DAO.
So localDataSource.getProducts()
is a observable read query
Observable queries are read operations that emit new values whenever there are changes to any of the tables that are referenced by the query.
Try to change LocalDataSource
interface SaleDao {
// fun getProducts(): Flow<List<Product>>
suspend fun getProducts(): List<Product>
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论