【译】LiveData的末日?StateFlow简介。

5,456 阅读2分钟


                            Photo by Jeremy Bishop on Unsplash

原文:medium.com/scalereal/s…


在本文中,我们将学习在Android开发中使用Koltin协程库中的StateFlow,来代替LiveData

在Kotlin协程库的最新版本(1.3.6)中,您可以看到一个新类-StateFlow。那么,这是什么以及它如何工作?让我们来看看… 

什么是StateFlow?

🤷‍♂️

- 这是一个 用来保存,修改状态 的新类型

- 他被设计用来取代 ConflatedBroadcastChannel ,适用于 状态发布 场景

- 他是一种Flow, 把数据(状态)更新发布给他的 collectors 

- 它的值 可以通过Flow 来观察🌊

还是疑惑?这里有个简单的demo

import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*

fun main() = runBlocking {
    val stateFlow = MutableStateFlow<Int>(0)

    // Observe values
    val job = launch {
        stateFlow.collect {
            print("$it ")
        }
    }

    // Change values
    (1..5).forEach {
        delay(500)
        stateFlow.value = it
    }

    // Cancel running job
    job.cancel()
    job.join()
}

                                             演示使用StateFlow

代码运行结果:0 1 2 3 4

我想你已经知道了StateFlow的含义,我们持续更新了StateFlow的值,然后StateFlow把值发送给了 collector。

为了在Android开发中管理状态, 我们通常使用 Android Arch  components 中的

LiveData,它具有生命周期感知的作用。我们可以用StateFlow来代替他,来看下怎么使用StateFlow吧,开始动手写一些代码。


⚡️ Getting Started

打开Android Studio并创建一个新项目。或者,您可以简答的克隆此仓库(this repository)。这是一个非常简单那的计数器应用,用于演示Kotlin Coroutine的StateFlow API的使用。

我们将使用MainViewModel来管理MainActivity的数据。

@ExperimentalCoroutinesApi

class MainViewModel : ViewModel() {

    private val _countState = MutableStateFlow<Int>(0)

    val countState: StateFlow<Int> = _countState

    fun incrementCount() {
        _countState.value++
    }

    fun decrementCount() {
        _countState.value--
    }
}

现在可以比较一下LiveData的实现了

--MutableStateFlow  
具有一个属性value,可以被设置

--我们声明了一个StateFlow类型的变量(比如 :countState)

--StateFlow有一个属性 value,你可以在任何时候安全的读取它的值



现在实现一下我们的MainActivity:

class MainActivity : AppCompatActivity() {

     private val viewModel by lazy {
         ViewModelProvider(this)[MainViewModel::class.java]
      }
   
     override fun onCreate(savedInstanceState: Bundle?) {
         super.onCreate(savedInstanceState)

         setContentView(R.layout.activity_main)

         initCountObserver()
         initView()
     }
}


这里我们初始化了我们的viewModel

接下来实现一下 initView方法:

private fun initView() {
    button_plus.setOnClickListener(::incrementCounter)
    button_minus.setOnClickListener(::decrementCounter)
}

 private fun incrementCounter(view: View) {
     viewModel.incrementCount()
 }

 private fun decrementCounter(view: View) {
     viewModel.decrementCount()
 }
    

我们计数器代码现在看起来都很ok 😃。

现在来观察一下我们的计数器的值:

private fun initCountObserver() {
    lifecycleScope.launch {
        viewModel.countState.collect { value ->
            textview_count.text = "$value"
        }
    }  
}


现在我们有一个collector,每次coutValue 更新的时候,collector就会执行相应的代码,因为我们使用了lifecycleScope,我们的collector具有了生命周期的感应能力,很简单对吧,是的😎。


运行一下代码:


这难道不香嘛?爱了爱了😍。


同样的效果,我们可以使用LiveData实现,他们之间有什么不同?

🤷‍♂️

我们可以对StateFlow使用功能強大的流运算符,例如Combine,Zip等,这可以为我们提供比LiveData更好的体验。对,就是那样。



最后的话:

--StateFlow非常易于处理和实现(【译者】:可以看作是 一个自带BackPressure处理的阻塞队列,队列的大小是1,collector要是跟不上StateFlow的更新速度,会观察到最新的值。)


--它的行为与LiveData相同,但具有更多的运算符和出色的性能😎。然后,我們应该考虑使用它而不是LiveData。


--因此,如果您觉得有帮助,請給我一些鼓掌(点赞) 👏 ,非常开心大家分享。


--分享即是关怀


--Thank You :) 🙏



资源:

-- StateFlow