【问题标题】:Does offer make the coroutines close or cancelled?报价是否使协程关闭或取消?
【发布时间】:2021-09-13 22:15:27
【问题描述】:

我正在查看 Android 开发者网站上的流程文档,我有一个问题。

https://developer.android.com/kotlin/flow#callback

如果你查看上面的链接,你会看到这样的代码。

class FirestoreUserEventsDataSource(
    private val firestore: FirebaseFirestore
) {
    // Method to get user events from the Firestore database
    fun getUserEvents(): Flow<UserEvents> = callbackFlow {

        // Reference to use in Firestore
        var eventsCollection: CollectionReference? = null
        try {
            eventsCollection = FirebaseFirestore.getInstance()
                .collection("collection")
                .document("app")
        } catch (e: Throwable) {
            // If Firebase cannot be initialized, close the stream of data
            // flow consumers will stop collecting and the coroutine will resume
            close(e)
        }

        // Registers callback to firestore, which will be called on new events
        val subscription = eventsCollection?.addSnapshotListener { snapshot, _ ->
            if (snapshot == null) { return@addSnapshotListener }
            // Sends events to the flow! Consumers will get the new events
            try {
                offer(snapshot.getEvents())
            } catch (e: Throwable) {
                // Event couldn't be sent to the flow
            }
        }

        // The callback inside awaitClose will be executed when the flow is
        // either closed or cancelled.
        // In this case, remove the callback from Firestore
        awaitClose { subscription?.remove() }
    }
}

在上面的代码中,awaitClose被解释为在协程关闭或取消时执行。

但是,除了初始化eventsCollection的try-catch语句之外,代码中没有close()。

另外,在 Android 开发者页面底部显示offer does not add the element to the channel and **returns false** immediately。

我的问题是,在上面的代码中,当offer(snapshot.getEvents())被执行时,协程是不是用return false取消,所以awaitClose被执行了?

【问题讨论】:

  • Offer 已弃用,应更改为 trySend
  • @Andrew 谢谢你告诉我!那么,trySend 取消与return false 的协程是否正确?

标签: android kotlin coroutine


【解决方案1】:

预期:

正如文档所说:

当您尝试向完整频道添加新元素时,send暂停 生产者,直到有新元素的空间,而 offer 确实 不将元素添加到频道并立即返回false。

尔格:

如果不违反其容量限制,则立即将指定元素添加到此通道,并返回成功结果。否则,返回失败或关闭的结果。这是 send 的同步变体,在 send 挂起或抛出的情况下会回退。

所以当trySend调用返回不成功的结果时,它保证该元素没有被传递给消费者,并且它不会调用为该通道安装的onUndeliveredElement。有关处理未交付元素的详细信息,请参阅频道文档中的“Undelivered elements”部分。

结论:

onDeliveredElement 的典型用法是关闭正在通过通道传输的资源。以下代码模式保证即使生产者、消费者和/或通道被取消,打开的资源也会关闭。 资源永远不会丢失。所以不,它不会返回false。

【讨论】:

  • 感谢您的详细和亲切的解释!我想我明白了。
  • 酷,如果您能将其标记为正确答案以帮助其他人(如果他们也需要对该主题的定义),那就太棒了! :) 干杯
  • 谢谢!我一直在寻找如何将这个答案作为答案。 (我是 Stack Overflow 的新手)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-02-01
  • 2012-09-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多