携手创造,一起生长!这是我参加「日新计划 8 月更文应战」的第18天,点击查看活动详情
本篇文章将是介绍
flow
一些常见API系列的第五篇文章,希望能够协助大家更好的把握flow运用,熟练的应用于各种场景。
历史文章
这些flow常见API的运用,你必定需求把握!(一)
这些flow常见API的运用,你必定需求把握!(二)
这些flow常见API的运用,你必定需求把握!(三)
这些flow常见API的运用,你必定需求把握!(四)
stateIn()
转变为暖流StateFlow
public fun <T> Flow<T>.stateIn(
scope: CoroutineScope,
started: SharingStarted,
initialValue: T
): StateFlow<T> {
val config = configureSharing(1)
val state = MutableStateFlow(initialValue)
val job = scope.launchSharing(config.context, config.upstream, state, started, initialValue)
return ReadonlyStateFlow(state, job)
}
-
冷流flow: 只有调用
collect{}
办法才会触发冷流履行 -
暖流:暖流的履行不依赖是否增加调查者
stateIn()
将冷流转换为暖流StateFlow()
,这个流有几个特色:
-
需求给予一个初始值
-
是一个粘性流,类似于
LiveData
,会重放最终一个更新数据 -
过滤重复数据,也便是说,发送重复数据会进行丢弃
-
供给
value
特点获取内部的值
一般能够用作代替LiveData,直接运用暖流作为ViewModel
中可调查的数据源,LiveData
能完成的它都能完成,不能完成的它也都能完成。
stateIn()
转变为暖流SharedFlow
public fun <T> Flow<T>.shareIn(
scope: CoroutineScope,
started: SharingStarted,
replay: Int = 0
): SharedFlow<T> {
val config = configureSharing(replay)
val shared = MutableSharedFlow<T>(
replay = replay,
extraBufferCapacity = config.extraBufferCapacity,
onBufferOverflow = config.onBufferOverflow
)
@Suppress("UNCHECKED_CAST")
val job = scope.launchSharing(config.context, config.upstream, shared, started, NO_VALUE as T)
return ReadonlySharedFlow(shared, job)
}
这个便是将冷流flow转换为SharedFlow
,上面的暖流StateFlow
完成了SharedFlow
,它首要有以下几个特色:
-
无法经过
.value
的方式拜访内部值 -
经过
replay
参数自定义你需求的粘性或非粘性的暖流
两种冷流都需求传递一个SharingStarted
类型的参数,这个参数有三种类型:Eagerly
、Lazily
、WhileSubscribed
决定暖流的启动模式,这儿首要介绍WhileSubscribed
:
public fun WhileSubscribed(
stopTimeoutMillis: Long = 0,
replayExpirationMillis: Long = Long.MAX_VALUE
): SharingStarted =
StartedWhileSubscribed(stopTimeoutMillis, replayExpirationMillis)
-
stopTimeoutMillis
:这个参数指定一个在最终一个订阅者撤销和中止流履行的时刻距离,意思便是当最终一个个订阅者撤销后,隔stopTimeoutMillis
ms之后再中止流的履行。 -
replayExpirationMillis
:这个参数指定一个再中止流履行和清除流缓存的时刻距离,也便是当中止流履行后,距离replayExpirationMillis
ms去清楚流的缓存。
举个应用场景,当应用反正屏切换时,订阅者就会被撤销,但是没必要去中止流履行或许整理缓存,由于反正屏往后很快就会重建从头显示,这样能更快的改写界面数据。
retryWhen{}
public fun <T> Flow<T>.retryWhen(predicate: suspend FlowCollector<T>.(cause: Throwable, attempt: Long) -> Boolean): Flow<T> =
flow {
var attempt = 0L
var shallRetry: Boolean
do {
shallRetry = false
val cause = catchImpl(this)
if (cause != null) {
if (predicate(cause, attempt)) {
shallRetry = true
attempt++
} else {
throw cause
}
}
} while (shallRetry)
}
这个办法也很有用,出现异常时进行重试,并决定是否重试仍是弹出提示信息,比方当咱们进行网络恳求时,恳求失利就能够运用这个办法,一方面在retryWhen{}
办法中记录错误信息并告诉下游流,一方面选择是否进行网络重试。
比方下面这个例子:
fun test2() {
GlobalScope.launch {
flow {
emit("${10 / 随机数}")
}
.retryWhen { cause, attempt ->
if (cause is ArithmeticException && attempt < 3) {
emit("retry")
true
} else {
false
}
}.collect {
println("jja: $it")
}
}
}
当上面的随机数出现0是就会触发ArithmeticException
异常,这样retryWhen{}
就能捕获并能够尝试重试,随机一个非0且能被整除的数,并且限制了重试次数为3次以为。
总结
关于flow常见api系列文章陆陆续续写了五篇了,暂时就告一段落,基本上常用的都介绍了一遍,希望能够给大家带来协助。