Kotlin Flow正在使用flatMapMerge进行重复执行。

huangapple go评论46阅读模式
英文:

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 Kotlin Flow正在使用flatMapMerge进行重复执行。

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 -&gt;
                productsList = products
                if (products != emptyList&lt;Product&gt;()) {
                    _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&lt;List&lt;Product&gt;&gt; {
        return localDataSource.getProducts().flatMapMerge { list -&gt; // LINE RUNNING INFINITELY
            getProductsFromFirebase(list, compnayName)
        }.flowOn(Dispatchers.IO).catch {
            Log.d(&quot;Error&quot;, it.message.toString())
        }
    }

    private fun getProductsFromFirebase(products: List&lt;Product&gt;, compnayName: String) = flow {
        if (products.isEmpty()) {
            remoteDataSource.getProducts(compnayName).collect {
                emit(it)
            }
        } else {
            emit(products)
        }
    }

LocalDataSource with Room:

override suspend fun getProducts(): Flow&lt;List&lt;Product&gt;&gt; = saleDao.getProducts()

Firebase Data Source:

    override suspend fun getProducts(company: String): Flow&lt;List&lt;Product&gt;&gt; = flow {
        val response = fireStore.collection(&quot;products&quot;).whereEqualTo(&quot;company&quot;, company).get()
        response.await()
        if (response.isSuccessful &amp;&amp; !response.result.isEmpty) {
            emit(response.result.toObjects(FirebaseProduct::class.java).toEntity())
        }
    }.catch {
        Log.d(&quot;Error&quot;, 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&lt;List&lt;Product&gt;&gt;
    suspend fun getProducts(): List&lt;Product&gt;
}

huangapple
  • 本文由 发表于 2023年2月19日 11:05:57
  • 转载请务必保留本文链接:https://go.coder-hub.com/75497752.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定