ade*_*111 5 android kotlin kotlin-coroutines kotlin-flow kotlin-coroutines-flow
我读过类似的主题,但找不到正确的答案:
在我的Repository
班级我感冒了Flow
,我想分享给 2 Presenters
/ViewModels
所以我的选择是使用shareIn
运算符。
让我们看一下 Android 文档的示例:
val latestNews: Flow<List<ArticleHeadline>> = flow {
...
}.shareIn(
externalScope, // e.g. CoroutineScope(Dispatchers.IO)?
replay = 1,
started = SharingStarted.WhileSubscribed()
)
Run Code Online (Sandbox Code Playgroud)
什么文档建议externalScope
参数:
用于共享流的 CoroutineScope。这个范围应该比任何消费者活得更久,以根据需要保持共享流的活动。
但是,寻找有关如何停止订阅 aFlow
的答案,第二个链接中投票最多的答案说:
解决方案不是取消流程,而是取消流程的范围。
对我来说,这些答案在SharedFlow
的情况下是矛盾的。不幸的是,即使在调用它之后,我的Presenter
/ViewModel
仍然会收到最新的数据onCleared
。
如何防止?这是我如何Flow
在我的Presenter
/ 中使用它的示例ViewModel
:
fun doSomethingUseful(): Flow<OtherModel> {
return repository.latestNews.map(OtherModel)
Run Code Online (Sandbox Code Playgroud)
如果这可能有帮助,我正在使用 MVI 架构,以便doSomethingUseful
对用户创建的某些意图做出反应。
感谢马克·基恩的评论和帖子,我想我取得了满意的结果。
我知道shareIn
参数中定义的范围不必与我的消费者操作的范围相同。BasePresenter
将/中的范围更改BaseViewModel
为CoroutineScope
toviewModelScope
似乎解决了主要问题。您甚至不需要手动取消此范围,如Android 文档中所定义:
init {
viewModelScope.launch {
// Coroutine that will be canceled when the ViewModel is cleared.
}
}
Run Code Online (Sandbox Code Playgroud)
请记住,默认viewModelScope
调度程序Main
并不明显,而且可能不是您想要的!要更改调度程序,请使用viewModelScope.launch(YourDispatcher)
.
更重要的是,我的热是从回调API(基于回调API)创建的SharedFlow
另一个冷转变而来的Flow
callbackFlow
Channels
API - 这很复杂......)
将集合范围更改为 后viewModelScope
,我在从该 API 发出新数据时遇到ChildCancelledException: Child of the scoped flow was cancelled
异常。这个问题在 GitHub 上的两个问题中都有详细记录:
如前所述,使用offer
和 的发射之间存在细微差别send
:
Offer 用于非挂起上下文,而 send 用于挂起上下文。
不幸的是,就传播的异常而言,offer 的发送是非对称的(发送中的 CancellationException 通常被忽略,而名义挂起上下文中的offer 中的 CancellationException 则不会)。
我们希望通过 OfferOrClosed 或更改 Offer 语义在 #974 中修复它
至于 1.4.2 的 Kotlin 协程,#974 尚未修复 - 我希望它会在不久的将来避免意外CancellationException
。
最后,我建议使用运算符started
中的参数shareIn
。在完成所有这些更改之后,我必须在我的用例中从 更改WhileSubscribed()
为。Lazily
如果我发现任何新信息,我会更新这篇文章。希望我的研究能够节省某人的时间。
归档时间: |
|
查看次数: |
1549 次 |
最近记录: |