livedata,stateflow,sharedflow,flow啥时候使用

https://www.youtube.com/watch?v=6Jc6-INantQ

学习笔记

在viewmodel中定义三个数据,确保只在内部进行修改,暴露只读的给外部监听

    private val _livedata = MutableLiveData("hello")
    val liveData: LiveData<String> = _livedata

    private val _stateFlow = MutableStateFlow("hello")
    val stateFlow = _stateFlow.asStateFlow()

    private val _sharedFlow = MutableSharedFlow<String>()
    val sharedFlow = _sharedFlow.asSharedFlow()

对应不同的按钮触发数据更改

    fun triggerLiveData() {
        _livedata.value = "livedata"
    }

    fun triggerStateFlow() {
        _stateFlow.value = "stateflow"
    }

    fun triggerFlow(): Flow<String> {
        return flow {
            repeat(5) {
                emit("item $it")
                delay(1000)
            }
        }
    }

    fun triggerSharedFlow(){
        viewModelScope.launch {
            _sharedFlow.emit("SharedFlow")
        }
    }

livedata 和 stateflow比较像,可以hold value,所以初始化的时候,都有传入默认的值

shareflow 和 flow 更像是事件,没有holdvalue

大部分情况下,对于UI的内容,我们使用stateflow比较多

Stateflow是热流,没有订阅者的话,也是会发送事件,然后flow还有很多操作组合等。

另外,当界面横竖屏切换的时候,因为stateflow可以hole值,所以内容还在

Shareflow 和stateflow一样,属于热流,但是Shareflow不会存值,所以横竖屏切换后,之前的值不在了,不会引发事件和更改。所以更适合做消息弹窗

flow是普通的流,是冷流,所以只有当订阅的时候,才开始发送事件,所以当触发triggerFlow的时候我们可以看到数据的发送过程,从0~4,监听到数据变化了,更新textview,当界面切换后,又回到原始的

 private fun subscribeData() {
        mainViewModel.liveData.observe(this) {
            binding.txtTest.text = it
        }

        lifecycleScope.launchWhenStarted {
            mainViewModel.stateFlow.collectLatest {
                //旋转界面值还在
                binding.txtTest.text = it


                //切换界面的时候,回重复出现,因为stateFlow可以缓存值,重新创建会发送
                Snackbar.make(binding.root,
                    it,
                    Snackbar.LENGTH_LONG)
                    .show()
            }
        }

        lifecycleScope.launchWhenStarted {
            mainViewModel.sharedFlow.collectLatest {
                //旋转界面,值不在了,因为 sharedFlow 没有存储值
                binding.txtTest.text = it


                //旋转切换界面,不会重复弹出,除非再次触发emit
                Snackbar.make(binding.root,
                    it,
                    Snackbar.LENGTH_LONG)
                    .show()
            }
        }

    }

    private fun onButtonClick(){
        lifecycleScope.launch {
            mainViewModel.triggerFlow().collectLatest {
                binding.txtTest.text = it
            //点击按钮,会0-4的变化,然后停止,但是界面切换之后,恢复到hello
            }
        }
    }
    private fun onButtonClick2(){
       mainViewModel.triggerSharedFlow()
    }

在加一个stateflow 和Shareflow的对比

 private val _sharedFlow = MutableSharedFlow<String>()
    val sharedFlow = _sharedFlow.asSharedFlow()

    fun triggerStateFlow() {
        _stateFlow.value = "stateflow"
    }


    fun triggerSharedFlow(value:Int){
        viewModelScope.launch {
            _sharedFlow.emit("SharedFlow $value")
        }
    }

    fun collectShareFlow(){
        triggerSharedFlow(1)

        viewModelScope.launch {
            //这里用collect 而不是 collectLatest
            //因为我们不想丢失事件
            sharedFlow.collect{
                delay(1000)
                println("sharedFlow: 1 received $it")
            }
        }
        triggerSharedFlow(2)


        viewModelScope.launch {
            sharedFlow.collect{
                delay(2000)
                println("sharedFlow: 2 received $it")
            }
        }

        triggerSharedFlow(3)
    }

发送了三次时间1、2、3,

1 实在两个订阅之前,2实在两个订阅之间,3 是在两个订阅之后

1  两个订阅都没有收到,因为Shareflow是热流,即使没有订阅也会发送事件,所以在两个订阅开始之前,这个事件就丢失了

2.是在1订阅之后,所以1收到到事件2,

3是在两个订阅之后的,所以两个订阅都收到到了3

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值