• StateFlow 和 SharedFlow


    一 官网地址

    转自 https://developer.android.google.cn/kotlin/flow/stateflow-and-sharedflow?hl=zh-cn

    StateFlow 和 SharedFlow 是 Flow API,允许数据流以最优方式发出状态更新并向多个使用方发出值。

    二 StateFlow

    StateFlow 是一个状态容器可观察数据流,可向其收集器发出当前状态更新和新状态更新。也可以通过其 value 属性读取当前状态值。如需更新状态并将其发送到数据流,请为 MutableStateFlow 类的 value 属性分配一个新值。

    class LatestNewsViewModel(
        private val newsRepository: NewsRepository
    ) : ViewModel() {
    
        // Backing property to avoid state updates from other classes
        private val _uiState = MutableStateFlow(LatestNewsUiState.Success(emptyList()))
        // The UI collects from this StateFlow to get its state updates
        val uiState: StateFlow<LatestNewsUiState> = _uiState
    
        init {
            viewModelScope.launch {
                newsRepository.favoriteLatestNews
                    // Update View with the latest favorite news
                    // Writes to the value property of MutableStateFlow,
                    // adding a new element to the flow and updating all
                    // of its collectors
                    .collect { favoriteNews ->
                        _uiState.value = LatestNewsUiState.Success(favoriteNews)
                    }
            }
        }
    }
    
    // Represents different states for the LatestNews screen
    sealed class LatestNewsUiState {
        data class Success(val news: List<ArticleHeadline>): LatestNewsUiState()
        data class Error(val exception: Throwable): LatestNewsUiState()
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    StateFlow、Flow 和 LiveData

    StateFlow 和 LiveData 有所不同:

    • StateFlow 需要将初始状态传递给构造函数,而 LiveData 不需要。
    • 当 View 进入 STOPPED 状态时,LiveData.observe() 会自动取消注册使用方,而从 StateFlow 或任何其他数据流收集数据的操作并不会自动停止。如需实现相同的行为,您需要从 Lifecycle.repeatOnLifecycle 块收集数据流。

    三 利用 shareIn 使冷数据流变为热数据流

    StateFlow 是热数据流,只要该数据流被收集,或对它的任何其他引用在垃圾回收根中存在,该数据流就会一直存于内存中。您可以使用 shareIn 运算符将冷数据流变为热数据流。

    以在 Kotlin 数据流中创建的 callbackFlow 为例,您无需为每个收集器都创建一个新数据流,而是可以使用 shareIn 在收集器间共享从 Firestore 检索到的数据。您需要传入以下内容:

    • 用于共享数据流的 CoroutineScope。此作用域函数的生命周期应长于任何使用方,使共享数据流在足够长的时间内保持活跃状态。
    • 要重放 (replay) 至每个新收集器的数据项数量。
    • “启动”行为政策。
    class NewsRemoteDataSource(...,
        private val externalScope: CoroutineScope,
    ) {
        val latestNews: Flow<List<ArticleHeadline>> = flow {
            ...
        }.shareIn(
            externalScope,
            replay = 1,
            started = SharingStarted.WhileSubscribed()
        )
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    四 SharedFlow

    shareIn 函数会返回一个热数据流 SharedFlow,此数据流会向从其中收集值的所有使用方发出数据。SharedFlow 是 StateFlow 的可配置性极高的泛化数据流。

    // Class that centralizes when the content of the app needs to be refreshed
    class TickHandler(
        private val externalScope: CoroutineScope,
        private val tickIntervalMs: Long = 5000
    ) {
        // Backing property to avoid flow emissions from other classes
        private val _tickFlow = MutableSharedFlow<Unit>(replay = 0)
        val tickFlow: SharedFlow<Event<String>> = _tickFlow
    
        init {
            externalScope.launch {
                while(true) {
                    _tickFlow.emit(Unit)
                    delay(tickIntervalMs)
                }
            }
        }
    }
    
    class NewsRepository(
        ...,
        private val tickHandler: TickHandler,
        private val externalScope: CoroutineScope
    ) {
        init {
            externalScope.launch {
                // Listen for tick updates
                tickHandler.tickFlow.collect {
                    refreshLatestNews()
                }
            }
        }
    
        suspend fun refreshLatestNews() { ... }
        ...
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36

    自定义 SharedFlow 行为

    • 通过 replay,您可以针对新订阅者重新发送多个之前已发出的值。
    • 通过 onBufferOverflow,您可以指定相关政策来处理缓冲区中已存满要发送的数据项的情况。默认值为 BufferOverflow.SUSPEND,这会使调用方挂起。其他选项包括 DROP_LATEST 或 DROP_OLDEST。
  • 相关阅读:
    微信小程序开发学习5(自定义组件)
    美客多、亚马逊卖家如何运用自养账号进行有效测评?
    听GPT 讲Rust源代码--library/std(16)
    coreldraw2018零售版最新下载步骤
    [项目管理-2]:软硬件项目管理 - 干系人管理、实践活动、常见工具
    adb 命令扩展
    Scala入门到精通(尚硅谷学习笔记)章节一——scala入门
    9、大小屏分离与精细化审核
    C语言双向链表
    智能汽车能否真正实现无人驾驶,为什么?
  • 原文地址:https://blog.csdn.net/baopengjian/article/details/134061339