美文网首页Android
协程中的StateFlow与ShareFlow

协程中的StateFlow与ShareFlow

作者: 安安_660c | 来源:发表于2022-06-21 21:17 被阅读0次

    流的冷热之分

    使用过RxJava的同学都知道,在RxJava中流存在冷流和热流这么一种说法的,那么冷流和热流有什么区别呢?

    • 冷流:在流未进行收集或者订阅的时候,整条操作链是不会运行,并且不会向接收者推送数据。订阅者之间也不会存在值共享
    • 热流:在订阅或者收集之前值就会产生,并且当有新的订阅者时,他会接收到订阅之后流中所发送的所有值,存在值共享

    Flow中也会存在冷流、热流之分,今天介绍的StateFlowShareFlow就是属于热流,那么就进入今天的正文

    StateFlow

    StateFloW是一个可观察的状态容器,我们可以通过value属性进行状态的更新和状态的当前状态值的读取,这一点是不是和我们平常使用flow的时候不一样呢,在冷流中我们是使用emit(),和构建流的同时来进行值的发射

    StateFlow的创建

    1、使用构造方法进行创建,并且设定一个初始值

    val state = MutableStateFlow<String>("default")
    
    

    2、状态的更新

    state.value = "pushNewValue"
    
    

    3、状态收集(collect是suspend函数,所以收集状态需要在协程作用域范围内)

    GlobalScope.launch(Dispatchers.IO){
        state.collect{
            Log.d("StateFlow",it)
        }
    }
    
    

    StateFlow使用示例

    下面通过一个示例来演示以下

    class loginviewModel(){
        val loginSuccess = MutableStateFlow<Boolean>(false)
        
        fun login(){
            lifecycleScope.launch{
              repository.login()
                .loading()
                .catch()
                .collect{
                   loginSuccess.value = true 
                }
            }
        }
    }
    
    

    HomeActvity.class

    class LoginActivity : AppCompatActivity(){
        override fun onCreate(){
            ...
            lifecycleScope.launch{
                viewModel.loginSuccess.collect{
                    //UI逻辑
                    ....
                }
            }
        }
    }
    
    

    上面示例会发现,这种开发模式在我们使用LiveData时具有相同的地方,两者都是可观察的数据容器,所以坊间传闻StateFlow会替代LiveData,我们了解下二者有何区别,你就会得到答案

    • StateFlow在构建时需要给定初始状态值,LiveData是不需要初始状态的
    • 如果当Activity进入后台时,Livedata会自动帮我们把使用方取消注册,但是StateFlow并没有关联生命周期,所以不会停止状态的更新推送,如果需要实现一样的功能,官方推荐我们在lifeCycle.repeatOnLifeCycle中进行数据的收集 ,也可以在生命周期函数中将Job.cancel()

    SharedFlow

    ShareFlowStateFlow类似,都是热流,但是SharedFlow更为灵活,但是区别在于SharedFLOW并不支持将旧值发送给新的订阅者,并且可以缓存策略,接下来我们看下怎么使用

    SharedFlow的创建

    val connectState = MutableSharedFlow<Boolean>(0,0,BufferOverflow.SUSPEND)
    
    
    public fun <T> MutableSharedFlow(
        replay: Int = 0,
        extraBufferCapacity: Int = 0,
        onBufferOverflow: BufferOverflow = BufferOverflow.SUSPEND
    ): MutableSharedFlow<T> {
        ...
    }
    
    

    上面为MutableSharedFlow的创建源码,需要了解他的三个配置参数

    • replay :当新的订阅者订阅需要重新将多少旧值重放给它

    • extraBufferCapacity :除开replay之外的缓冲区大小

    • onBufferOverflow :缓冲区溢出策略

       SUSPEND:缓冲区满时就会被挂起
       DROP_OLDEST: 缓冲区满时就会删除最旧的值
       DROP_LATEST:删除即将进入缓冲区的最新值
      
      

    使用emit或者tryEmit进行值的发送

     connectState.tryEmit(false)
     connectState.emit(false)
    
    

    tryEmit会将发射的结果回调,并且如果缓冲区策略配置为suspend时会将这次数据的发射挂起,知道缓冲区有空间时再进行发射。

    emit 当缓冲区没有空间时,该操作就会挂起

    SharedFlow的收集

    GlobalScope.launch(Dispatchers.IO){
        connectstate.collect{
            ...
        }
    }
    
    

    冷流转换成热流

    官方分别提供stateIn使Flow转换成StateFlow以及使用shareIn操作符转换为SharedFlow

    class HomeViewModel(){
        val homeState:Flow<ViewState> = flowof{
            ViewState.Loading
        }.stateIn(coroutineScope)
    }
    
    

    使用shareIn进行转换需要了解它的参数配置

    public fun <T> Flow<T>.shareIn(
        scope: CoroutineScope,
        started: SharingStarted,
        replay: Int = 0
    )
    
    
    • scope: sharedFlow的启动作用域
    • started:启动策略
      • SharingStarted.WhileSubscribed() 如果存在数据收集者,上游数据提供方保持活跃状态
      • SharingStarted.Eagerly 立即启动数据提供方
      • SharingStarted.Lazily存在数据收集者开始提供数据,并且永远保持活跃状态

    相关文章

      网友评论

        本文标题:协程中的StateFlow与ShareFlow

        本文链接:https://www.haomeiwen.com/subject/emnevrtx.html