Android

协程中的StateFlow与ShareFlow

2022-06-21  本文已影响0人  安安_660c

流的冷热之分

使用过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,我们了解下二者有何区别,你就会得到答案

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的创建源码,需要了解他的三个配置参数

使用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
)

上一篇下一篇

猜你喜欢

热点阅读