英超联赛杯直播在线观看 官方选举 Flow 取代 LiveData,有必要吗?
发布日期:2021-09-10 21:16    点击次数:68

序言 英超联赛杯直播在线观看

掀开Android架构组件页面,吾们能够发现一些最新发布的jetpack组件,如Room,DataStore, Paging3,DataBinding 等都声援了Flow。Google开发者账号近来也发布了几篇行使Flow的文章,比如:从 LiveData 迁移到 Kotlin 数据流望首来官方在大力选举行使Flow取代LiveData,那么题目来了,有必要吗?

访问活动地址:

访问:

访问:

访问:

访问:

吾LiveData用得益益的,有必要再学Flow吗?本文主要回答这个题目,详细包括以下内容:

LiveData有什么不及? Flow介绍以及为什么会有Flow SharedFlow与StateFlow的介绍与它们之间的区别

本文详细现在录如下所示:

1. LiveData有什么不及? 1.1 为什么引入LiveData?

要晓畅LiveData的不及,吾们先晓畅下LiveData为什么被引入

LiveData 的历史要追溯到 2017 年。彼时,不都雅察者模式有效简化了开发,但诸如 RxJava 一类的库对新手而言有些太甚复杂。为此,架构组件团队打造了 LiveData: 一个专用于 Android 的具备自立生命周期感知能力的可不都雅察的数据存储器类。 LiveData被有意简化设计,这使得开发者很容易上手;而对于较为复杂的交互数据流场景,提出您行使 RxJava,云云两者结相符的上风就发挥出来了

能够望出英超联赛杯直播在线观看,LiveData就是一个浅易易用的,具备感知生命周期能力的不都雅察者模式

它行使首来专门浅易,这是它的益处,也是它的不及,由于它面对比较复杂的交互数据流场景时,处理首来比较麻烦。

1.2 LiveData的不及

吾们上文说过LiveData组织浅易,但是不足富强,它有以下不及

LiveData只能在主线程更新数据 LiveData的操作符不足富强,在处理复杂数据流时有些捉襟见肘

关于LiveData只能在主线程更新数据,有的同学能够要问,不是有postValue吗?其实postValue也是必要切换到到主线程的,如下图所示:

这意味着当吾们想要更新LiveData对象时,吾们会往往更改线程(做事线程→主线程),倘若在修改LiveData后又要切换回到做事线程那就更麻烦了,同时postValue能够会有丢数据的题目。

2. Flow介绍

Flow 就是 Kotlin 协程与反响式编程模型结相符的产物,你会发现它与 RxJava 专门像,二者之间也有相互转换的 API,行使首来专门方便。

2.1 为什么引入Flow

为什么引入Flow,吾们能够从Flow解决了什么题目的角度切入

LiveData不声援线程切换,一切数据转换都将在主线程上完善,未必必要反复更改线程,面对复杂数据流时处理首来比较麻烦。

而RxJava又有些过于麻烦了,有很众让人傻傻分不清的操作符,入门门槛较高,同时必要本身处理生命周期,在生命周期终结时作废订阅

能够望出英超联赛杯直播在线观看,Flow是介于LiveData与RxJava之间的一个解决方案,它有以下特点

Flow 声援线程切换、背压 Flow 入门的门槛很矮,异国那么众傻傻分不晓畅的操作符 浅易的数据转换与操作符,如 map 等等 冷数据流,不消耗则不生产数据,这一点与LiveData分歧:LiveData的发送端并不倚赖于授与端。属于kotlin协程的一片面,能够很益的与协程基础设施结相符

关于Flow的行使,比较浅易,兴趣味的同学可参阅文档:Flow文档

3. SharedFlow介绍

吾们上面介绍过,Flow 是冷流,什么是冷流?

冷流 :只有订阅者订阅时,才最先实走发射数据流的代码。并且冷流和订阅者只能是一对一的有关,当有众个分歧的订阅者时,新闻是重新完善发送的。也就是说对冷流而言,有众个订阅者的时候,他们各自的事件是自力的。

炎流:不论有异国订阅者订阅,事件首终都会发生。当 炎流有众个订阅者时,炎流与订阅者们的有关是一对众的有关,能够与众个订阅者共享新闻。

3.1 为什么引入SharedFlow

上面其实已经说得很晓畅了,冷流和订阅者只能是一对一的有关,当吾们要实现一个流,众个订阅者的需求时(这在开发中是很常见的),就必要炎流了 遵命名上也很容易理解,SharedFlow即共享的Flow,能够实现一对众有关,SharedFlow是一栽炎流

3.2 SharedFlow的行使

吾们来望望SharedFlow的组织函数

public fun <T> MutableSharedFlow(     replay: Int = 0,     extraBufferCapacity: Int = 0,     onBufferOverflow: BufferOverflow = BufferOverflow.SUSPEND ): MutableSharedFlow<T

其主要有3个参数

replay外示当新的订阅者Collect时,发送几个已经发送过的数据给它,默认为0,即默认新订阅者不会获取以前的数据 extraBufferCapacity外示减去replay,MutableSharedFlow还缓存众幼批据,默认为0 onBufferOverflow外示缓存策略,即缓冲区满了之后Flow如那里理,默认为挂首

浅易行使如下:

//ViewModel val sharedFlow=MutableSharedFlow<String>()  viewModelScope.launch{       sharedFlow.emit("Hello")       sharedFlow.emit("SharedFlow") }  //Activity lifecycleScope.launch{     viewMode.sharedFlow.collect {         print(it)     } } 
3.3 将冷流转化为SharedFlow

清淡flow可行使shareIn扩展手段,转化成SharedFlow

val sharedFlow by lazy {       flow<Int> {       //...       }.shareIn(viewModelScope, WhileSubscribed(500), 0)   } 

shareIn主要也有三个参数:

@param scope 共享最先时所在的协程作用域周围 @param started 限制共享的最先和终结的策略 @param replay 状态流的重播个数

started 批准以下的三个值:

Lazily: 当首个订阅者显眼前最先,在scope指定的作用域被终结时终止。 Eagerly: 立即最先,而在scope指定的作用域被终结时终止。 WhileSubscribed: 这栽情况有些复杂,后面会详细讲解

对于那些只实走一次的操作,您能够行使Lazily或者Eagerly。然而,倘若您必要不都雅察其他的流,就答该行使WhileSubscribed来实现微弱但又主要的优化做事

3.4 Whilesubscribed策略

WhileSubscribed策略会在异国搜集器的情况下作废上游数据流,始末shareIn运算符创建的SharedFlow会把数据袒露给视图 (View),同时也会不都雅察来自其他层级或者是上游行使的数据流。

让这些流不息活跃能够会引首不消要的资源铺张,例如不息始末从数据库连接、硬件传感器中读取数据等等。当您的行使转而在后台运走时,您答当保持约束并休止这些协程。

public fun WhileSubscribed(    stopTimeoutMillis: Long = 0,    replayExpirationMillis: Long = Long.MAX_VALUE ) 

如上所示,它声援两个参数:

stopTimeoutMillis 限制一个以毫秒为单位的延长值,指的是末了一个订阅者终结订阅与停留上游流的时间差。默认值是 0 (立即停留).这个值专门有效,由于您能够并不想由于视图有几秒钟不再监听就终结上游流。这栽情况非往往见——比如当用户旋转设备时,正本的视图会先被烧毁,然后数秒钟内重修。 replayExpirationMillis外示数据重播的过往往间,倘若用户脱离行使太久,此时您不想让用户望到破旧的数据,你能够用到这个参数 4. StateFlow介绍 4.1 为什么引入StateFlow

吾们前线刚刚望了SharedFlow,为什么又冒出个StateFlow?

StateFlow 是 SharedFlow 的一个比较稀奇的变栽,StateFlow 与 LiveData是最挨近的,由于:

它首终是有值的。 它的值是唯一的。 它批准被众个不都雅察者共用 (因此是共享的数据流)。 它永久只会把最新的值重现给订阅者,这与活跃不都雅察者的数目是无关的。

能够望出英超联赛杯直播在线观看,StateFlow与LiveData是比较挨近的,能够获取现在的值,能够想像之因此引入StateFlow就是为了替换LiveData

总结如下:

StateFlow继承于SharedFlow,是SharedFlow的一个稀奇变栽 StateFlow与LiveData比较相近,坚信之因此推出就是为了替换LiveData 4.2 StateFlow的浅易行使

吾们先来望望组织函数:

public fun MutableStateFlow(value: T): MutableStateFlow = StateFlowImpl(value ?: NULL)

StateFlow组织函数较为浅易,只必要传入一个默认值 StateFlow内心上是一个replay为1,并且异国缓冲区的SharedFlow,因此第一次订阅时会先获得默认值 3.StateFlow仅在值已更新,并且值发生了转折时才会返回,即倘若更新后的值异国转折,也没会回调Collect手段,这点与LiveData分歧

与SharedFlow相通,吾们也能够用stateIn将清淡流转化成StateFlow

val result: StateFlow<Result<UiState>> = someFlow     .stateIn(         scope = viewModelScope,          started = WhileSubscribed(5000),          initialValue = Result.Loading     ) 

与shareIn相通,唯一分歧的时必要传入一个默认值 同时之因此WhileSubscribed中传入了5000,是为了实现期待5秒后照样异国订阅者存在就终止协程的功能,这个手段有以下功能

用户将您的行使转至后台运走,5 秒钟后一切来自其他层的数据更新会停留,云云能够撙节电量。最新的数据照样会被缓存,因此当用户切换回行使时,视图立即就能够得到数据进走渲染。订阅将被重启,新数据会填充进来,当数据可用时更新视图。

在屏幕旋转时,由于重新订阅的时间在5s内,因此上游流不会休止

4.3 在页面中不都雅察StateFlow

与LiveData相通,吾们也必要往往在页面中不都雅察StateFlow

不都雅察StateFlow必要在协程中,因此吾们必要协程构建器,清淡吾们会行使下面几栽

lifecycleScope.launch : 立即启动协程,并且在本 Activity或Fragment 烧毁时终结协程。 LaunchWhenStarted 和 LaunchWhenResumed,它会在lifecycleOwner进入X状态之前不息期待,又在脱离X状态时挂首协程

如上图所示:

行使launch是担心然的,在行使在后台时也会授与数据更新,能够会导致行使休业 行使launchWhenStarted或launchWhenResumed会益一些,在后台时不会授与数据更新,但是,上游数据流会在行使后台运走期间保持活跃,因此能够铺张必定的资源

这么说来,吾们行使WhileSubscribed进走的配置岂不是无效了吗?订阅者不息存在,只有页面关闭时才会作废订阅

官方选举repeatOnLifecycle来构建协程

在某个特定的状态已足时启动协程,并且在生命周期一切者退出该状态时停留协程,如下图所示。

比如在某个Fragment的代码中:

onCreateView(...) {     viewLifecycleOwner.lifecycleScope.launch {         viewLifecycleOwner.lifecycle.repeatOnLifecycle(STARTED) {             myViewModel.myUiState.collect { ... }         }     } } 

当这个Fragment处于STARTED状态时会最先搜集流,并且在RESUMED状态时保持搜集,最后在Fragment进入STOPPED状态时终结搜集过程。

结相符行使repeatOnLifecycle API和WhileSubscribed,能够协助您的行使妥善行使设备资源的同时,发挥最佳性能

4.4 页面中不都雅察Flow的最佳手段

始末ViewModel袒露数据,并在页面中获取的最佳手段是:

行使带超时参数的 WhileSubscribed 策略袒露 Flow。示例 1 行使 repeatOnLifecycle 来搜集数据更新。示例 2

最佳实践如上图所示,倘若采用其他手段,上游数据流会被不息保持活跃,导致资源铺张 自然,倘若您并不必要行使到Kotlin Flow的富强功能,就用LiveData益了 :)

5 StateFlow与SharedFlow有什么区别?

从上文其实能够望出英超联赛杯直播在线观看,StateFlow与SharedFlow其实是挺像的,让人有些傻傻分不清,未必候也挺难选择该用哪个的 吾们总结一下,它们的区别如下:

SharedFlow配置更为变通,声援配置replay,缓冲区大幼等,StateFlow是SharedFlow的特化版本,replay固定为1,缓冲区大幼默认为0 StateFlow与LiveData相通,声援始末myFlow.value获取现在状态,倘若有这个需求,必须行使StateFlow SharedFlow声援发出和搜集重复值,而StateFlow当value重复时,不会回调collect

对于新的订阅者,StateFlow只会重播现在最新值,SharedFlow可配置重播元素个数(默认为0,即不重播)

能够望出英超联赛杯直播在线观看,StateFlow为吾们做了一些默认的配置,在SharedFlow上增补了一些默认收敛,这些配置能够并不相符吾们的请求

它无视重复的值,并且是不走配置的。这会带来一些题目,比如当去List中增补元素并更新时,StateFlow会认为是重复的值并无视 它必要一个初首值,并且在最先订阅时会回调初首值,这有能够不是吾们想要的 它默认是粘性的,新用户订阅会获得现在的最新值,而且是不走配置的,而SharedFlow能够修改replay

StateFlow施添在SharedFlow上的收敛能够不是最正当您,倘若不必要访问myFlow.value,并且享福SharedFlow的变通性,能够选择考虑行使SharedFlow

总结

浅易往往意味着不足富强,而富强又往往意味着复杂,两者往往不及兼得,柔件开发过程中往往面临这栽取弃。

LiveData的浅易并不是它的弱点,而是它的特点。StateFlow与SharedFlow更强化盛,但是学习成本也隐微的更高。

吾们答该按照本身的需求相符理选择组件的行使

倘若你的数据流比较浅易,不必要进走线程切换与复杂的数据变换,LiveData对你来说坚信已经有余了 倘若你的数据流比较复杂,必要切换线程等操作,不必要发送重复值,必要获取myFlow.value,StateFlow对你来说是个益的选择

倘若你的数据流比较复杂,同时不必要获取myFlow.value,必要配置新用户订阅重播无素的个数英超联赛杯直播在线观看,或者必要发送重复的值,能够考虑行使SharedFlow