gpt4 book ai didi

android - Kotlin 流 : unsubscribe from SharedFlow when Fragment becomes invisible

转载 作者:行者123 更新时间:2023-12-04 11:23:08 25 4
gpt4 key购买 nike

我读过类似的主题,但找不到正确的答案:

  • How to end / close a MutableSharedFlow?
  • Kotlin Flow: How to unsubscribe/stop
  • StateFlow and SharedFlow. Making cold flows hot using shareIn - Android 文档
  • Introduce SharedFlow - GH 讨论由 Roman Elizarov
  • 发起

    在我的 Repository上课我感冒了 Flow我想分享给 2 Presenters/ ViewModels所以我的选择是使用 shareIn运算符(operator)。
    让我们看一下 Android 文档的示例:
    val latestNews: Flow<List<ArticleHeadline>> = flow {
    ...
    }.shareIn(
    externalScope, // e.g. CoroutineScope(Dispatchers.IO)?
    replay = 1,
    started = SharingStarted.WhileSubscribed()
    )
    文档对 externalScope 的建议是什么?范围:

    A CoroutineScope that is used to share the flow. This scope should live longer than any consumer to keep the shared flow alive as long as needed.


    但是,寻找有关如何停止订阅 Flow 的答案,第二个链接中投票最多的答案说:

    A solution is not to cancel the flow, but the scope it's launched in.


    对我来说,这些答案在 SharedFlow 中是矛盾的。的情况。不幸的是我的 Presenter/ ViewModel即使在其 onCleared 之后仍会收到最新数据被称为。
    如何防止这种情况?这是我如何使用 Flow 的示例在我的 Presenter/ ViewModel :
    fun doSomethingUseful(): Flow<OtherModel> {
    return repository.latestNews.map(OtherModel)
    如果这可能有帮助,我正在使用 MVI 架构,所以 doSomethingUseful对用户创建的一些 Intent 使用react。

    最佳答案

    感谢 Mark Keen 的评论和帖子,我想我设法获得了令人满意的结果。
    我了解 shareIn 中定义的范围参数不必与我的消费者操作的范围相同。在 BasePresenter 中更改范围/BaseViewModel来自 CoroutineScopeviewModelScope似乎解决了主要问题。您甚至不需要手动取消此范围,如 Android docs 中所定义。 :

    init {
    viewModelScope.launch {
    // Coroutine that will be canceled when the ViewModel is cleared.
    }
    }
    请记住默认 viewModelScope调度员是 Main这并不明显,它可能不是你想要的!要更改调度程序,请使用 viewModelScope.launch(YourDispatcher) .
    更何况我的热门 SharedFlow由另一种寒冷转变而来 Flow创建于 callbackFlow回调 API(基于 Channels API - 这很复杂...)
    将收集范围更改为 viewModelScope 后,我得到 ChildCancelledException: Child of the scoped flow was cancelled从该 API 发出新数据时出现异常。这个问题在 GitHub 上的两个问题中都有很好的记录:
  • kotlinx.coroutines.flow.internal.ChildCancelledException: Child of the scoped flow was cancelled
  • SendChannel.offer should never throw

  • 如前所述,使用 offer 的发射之间存在细微差别。和 send :

    offer is for non-suspending context, while send is for suspending ones.


    offer is, unfortunately, non-symmetric to send in terms of propagated exceptions (CancellationException from send is usually ignored, while CancellationException from offer in nom-suspending context is not).


    We hope to fix it in #974 either with offerOrClosed or changing offer semantics


    至于 1.4.2 的 Kotlin Coroutines,#974 还没有修复 - 我希望它会在不久的将来避免意外 CancellationException .
    最后,我建议玩 started shareIn 中的参数运算符(operator)。在所有这些更改之后,我不得不从 WhileSubscribed() 更改至 Lazily在我的用例中。
    如果我发现任何新信息,我会更新这篇文章。希望我的研究能节省一些人的时间。

    关于android - Kotlin 流 : unsubscribe from SharedFlow when Fragment becomes invisible,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66267722/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com