Photo by Jeremy Bishop on Unsplash
在本文中,我们将学习在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 中的
⚡️ 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的实现了
--我们声明了一个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 :) 🙏