Android Flow 操作符大全

本文详细介绍了Android中Kotlin的Flow操作符,包括创建、变换、过滤、组合、功能性、回调和末端操作符,以及特定于Android平台的转换。Flow提供了一种处理数据流的方式,允许在不使用值的情况下修改数据,适用于Android开发中的数据管理和异步操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

概述

可以利用中间运算符在不使用值的情况下修改数据流。中间运算符可以接连应用,形成链式运算,在数据项被发送到数据流时延迟执行。

其中操作符还分为三大类:

  1. 创建操作符
  2. 中间操作符
  3. 末端操作符

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-m20UOOOF-1670402776711)(/Users/apple/Downloads/job_files/flow/Xnip2022-11-20_15-33-21.jpg )]

创建操作符

flow
val f = flow {
    emit(1)
    emitAll(flowOf(1, 2, 3))
}
//  output
1
1
2
3

创建 Flow的基本方法. 使用 emit 发射单个值使用 emitAll 发射一个流 ,类似 list.addAll(list)

flowOf

快速创建 flow , 类似 listOf()

val f2 = flowOf("A", "B", "C")

// output
A
B
C
asFlow

将其他数据转换成 普通的flow ,一般是集合向Flow的转换

kotlin 标准库中提供了基本数据类型相关扩展方法,其中 Map类型不能直接使用asFlow() 需要转换成其支持的类型,再使用 asFlow().

fun testAsFlow3() {

    // Range 类型
    val flow1 = IntRange(1, 100).asFlow()
    val flow2 = LongRange(1L, 1000L).asFlow()
    
    // Array 类型
    val flow3 = intArrayOf(1, 2, 3).asFlow()
    val flow4 = longArrayOf(1L, 2L, 3L).asFlow()
    val flow5 = arrayOf("A", "B", "C").asFlow()
    
    // Sequence 类型
    val flow6 = sequenceOf("X", "Y", "Z").asFlow()
    
    // Iterable 类型
    val flow7 = listOf(1, 2, 3).asFlow()
    val flow8 = setOf("E", "G", "C").asFlow()
    
    // Iterator 类型
    val flow9 = iterator<Int> {}.asFlow()
    
    // Map 类型
	val map = hashMapOf(Pair("A", 1), Pair("B", 2))
	
	val flow10 = map.asIterable().asFlow()
	val flow11 = map.asSequence().asFlow()
	val flow12 = map.iterator().asFlow()
}
callbackFlow

将回调方法改造成 flow , 类似 suspendCoroutine

例如我们有以下,利用 RequestManagerRequestCallBack 模拟数据加载情况,将回调改造成支持 Flow

interface RequestCallBack {

    fun onStart()

    fun onSuccessFul(value: Int)

    fun onError(e: Throwable)

    fun onCompleted()

}

object RequestManager {

    private val callBacks = mutableListOf<RequestCallBack>()

    fun addRequestCallBack(callBack: RequestCallBack) {
        callBacks.add(callBack)
    }

    fun removeRequestCallBack(callBack: RequestCallBack) {
        callBacks.remove(callBack)
    }

    fun request() {
        callBacks.forEach {
            it.onStart()
        }
        try {
            val value = Random.nextInt()
            if (value % 2 == 0) {
                throw IllegalStateException("value % 2 != 0")
            }
            callBacks.forEach {
                it.onSuccessFul(value)
            }
        } catch (e: Exception) {
            callBacks.forEach {
                it.onError(e)
            }
        }
        callBacks.forEach {
            it.onCompleted()
        }
    }
}

利用callbackFlow函数,改造如下:

fun testCallBackFlow(): Flow<Int> = callbackFlow {
    val callback = object : RequestCallBack {
        override fun onStart() {
        }
        override fun onSuccessFul(value: Int) {
            trySend(value)  // 将数据发送到 flow中
        }
        override fun onError(e: Throwable) {
              close(e) // 抛出异常关闭
              close()  // 正常关闭, 不抛出异常
        }
        override fun onCompleted() {
             
        }
    }
    RequestManager.addRequestCallBack(callback)
    RequestManager.request()
    // 关闭之后回调
    awaitClose {
        RequestManager.removeRequestCallBack(callback)
    }
}
  1. 调用send()trySend() 将数据发送至 Flow
  2. 在回调结束调用 close() 关闭管道、其中close() 传入异常将末端收集不到出错前数据,如果不传则可以正常收集到.
  3. awitClose 扩展方法在 Flow管道close() 之后调用,可以在此处做数据回收等工作。

flow 构建器不同,callbackFlow 允许通过 send 函数从不同 CoroutineContext发出值

在协程内部,callbackFlow 会使用通道,它在概念上与阻塞队列非常相似。通道都有容量配置,限定了可缓冲元素数的上限。在 callbackFlow 中所创建通道的默认容量为 64 个元素。当您尝试向完整通道添加新元素时,send 会将数据提供方挂起,直到新元素有空间为止.

emptyFlow
val f3 = emptyFlow<Int>()

返回一个空流。

channelFlow

在一般的flow在构造代码块中不允许切换线程,ChannelFlow则允许内部切换线程

val f4 = channelFlow<Int> {
    send(1)
    
    withContext(Dispatchers.IO) {
        send(2)
    }
    withContext(Dispatchers.Default) {
        send(3)
    }
}

// output
1
2
3

变换操作符

map

将发出的值 进行变换,lambda的返回值为最终发送的值

val flowMap = flow {
    emit(true)
}.map {
    return@map it.toString()
}
mapLatest

转换原始流数据,当原始流发出新值时,将取消对先前值的转换块的计算。

val flowMapLatest = flow {
    emit("a")
    delay(100)
    emit("b")
}.mapLatest { value ->
    println("Started computing $value")
    delay(200)
    "Computed $value"
}

// output
Started computing a
Started computing b
Computed b
mapNotNull

对数据流控制,仅发送 map 后不为空的值

val flowMapNoNull = flow {
    emitAll(flowOf("A", "B"))
}.mapNotNull {
    if (it == "B") {
        it
    } else {
        null
    }
}
// output
B
transform

对发出的值 进行变换 。区别于maptransform的接收者是FlowCollector ,因此它非常灵活,可以变换、跳过它或多次发送。

val flowTransform = flow {
    emitAll(flowOf("A", "B", "c", "d"))
}.transform { value ->
    if (value == "A" || value == "B") {
        emit("transform :${value.lowercase()}")
    } else {
        emit("value ${value.uppercase()}")
    }
}

// output
transform :a
transform :b
value C
value D
transformLatest

类比 mapLatest ,当有新值发送时如果上个变换还没结束,会先取消掉

val flowTransformLatest = flow {
    emit("a")
    delay(100)
    emit("b")
}.transformLatest { value ->
    emit(value)
    delay(200)
    emit(value + "_last")
}

// output
a
b
b_last
transformWhile

将转换函数应用于给定流的每个值,同时此函数返回 truetransformWhile 的接收者是 FlowCollector,因此 transformWhile 是一个灵活的函数,可以转换发射的元素、跳过它或多次发射它。此运算符概括了 takeWhile 并可用作其他运算符的构建块。例如,下载进度消息流可以在下载完成时完成,但会发出最后一条消息(与 takeWhile 不同)

val flowTransformWhite = flow {
    for (i in 1..4) {
        emit(i)
    }
}.transformWhile { value ->
    if (value > 2) {
        false
    } else {
        emit("value $value")
        true
    }
}

// output
value 1
value 2
asStateFlow

MutableStateFlow 转换为 StateFlow ,就是变成不可变的。常用在对外暴露属性时使用

private val _flowAsStateFlow = MutableStateFlow(UIState.INITIAL) 
val flowAsStateFlow = _flowAsStateFlow.asStateFlow()
asSharedFlow

MutableSharedFlow 转换为 SharedFlow ,就是变成不可变的。常用在对外暴露属性时使用

private val _asSharedFlow = MutableSharedFlow<UIState>()
val asSharedFlow = _asSharedFlow.asSharedFlow()
receiveAsFlow

Channel 转换为Flow ,可以有多个观察者,但不是多播,可能会轮流收到值。

private val _receiveAsFlow = Channel<UIState>()
val receiveAsFlow = _receiveAsFlow.receiveAsFlow()
consumeAsFlow

Channel 转换为Flow ,但不能多个观察者(会crash)

private val _consumeAsFlow = Channel<UIState>()
val consumeAsFlow = _consumeAsFlow.consumeAsFlow()
withIndex

将结果包装成IndexedValue 类型

public data class IndexedValue<out T>(public val index: Int, public val value: T)
val withIndex = flow {
    emit("A")
    emit("B")
}.withIndex()

// output
IndexedValue(index=0, value=A)
IndexedValue(index=1, value=B)
scan

fold 相似,区别是fold 返回的是最终结果,scan返回的是个flow ,会把初始值和每一步的操作结果发送出去。

val scan = flowOf(1, 2, 3)
    .scan(emptyList<Int>()) { acc, value ->
        acc + value
    }
    
// output
[]
[1]
[1, 2]
[1, 2, 3]
produceIn

转换为 ReceiveChannel , 不常用。

注: Channel 内部有 ReceiveChannel 和 SendChannel之分,看名字就是一个发送,一个接收。

val produceIn = flowOf(1, 2, 3).produceIn(viewModelScope)

// output
1
2
3
runningFold

区别于 fold ,就是返回一个新流,将每步的结果发射出去。

其实上述 scan 操作符内部也是调用的 runningFold

val runningFold = flowOf(1, 2, 3)
    .runningFold(emptyList<Int>()) { acc, value ->
        acc + value
    }
    
// output
[]
[1]
[1, 2]
[1, 2, 3]
runningReduce

区别于 reduce ,就是返回一个新流,将每步的结果发射出去。

val runningReduce = flowOf(1, 2, 3, 4)
    .runningReduce { acc, value ->
        acc + value
    }
    
// output
1
3
6
10

过滤操作符

filter

筛选出符合条件的值

val filter = flowOf("A", "B", "C")
    .filter {
        it != "B"
    }
    
// output
A
C
filterInstance

筛选对应类型的值

val filterIsInstance = flowOf("A", 1, false)
    .filterIsInstance<String>()
    
// output
A
filterNot

筛选不符合条件相反的值,相当于filter取反

val filterNot = flowOf("A", "B", "C")
    .filterNot {
        it == "A"
    }

// output
B
C
filterNotNull

筛选不为空的值

val filterNotNull = flowOf("A", null, "C")
    .filterNotNull()
    
// output
A
C
drop

作用是 丢弃掉前 n 个的值 , 入参countint类型

val drop = flowOf("A", "B", "C")
    .drop(2)

// output
C
dropWhile

这个操作符有点特别,和 filter 不同! 它是找到第一个不满足条件的,返回其和其之后的值。
如果首项就不满足条件,则是全部返回。

val dropWhile = flowOf("A", "B", "C")
    .dropWhile {
        it != "B"
    }
    
// output
take

返回前 n 个 元素

val take = flowOf("A", "B", "C")
    .take(2)
    
// output
A
B
takeWhile

也是找第一个不满足条件的项,但是取其之前的值 ,和dropWhile 相反。
如果第一项就不满足,则为空流

// ①
val takeWhile = flowOf("A", "B", "C")
    .takeWhile {
        it != "B"
    }
    
// output
A

// ②
val takeWhile2 = flowOf("A", "B", "C")
    .takeWhile { 
        it == "B"
    }.onEmpty {
        emit("empty")
    }
    
// output
empty
debounce

防抖节流 ,指定时间内的值只接收最新的一个,其他的过滤掉。

val debounce = flow {
    emit(1)
    delay(90)
    
    emit(2)
    delay(90)
    
    emit(3)
    delay(1010)
    
    emit(4)
    delay(1010)
    
    emit(5)
}.debounce(1000)

// output
3
4
5
sample

采样. 给定一个时间周期,仅获取周期内最新发出的值

val sample = flow {
    repeat(10) {
        emit(it)
        delay(110)
    }
}.sample(200)

// output
1
3
5
7
9
distinctUntilChangedBy

去重操作符,判断连续的两个值是否重复,可以选择是否丢弃重复值。

val distinctUntilChangedBy = flow {
    emit(User(1, "Tom"))
 
    emit(User(3, "Tom"))
    emit(User(3, "Tom"))
 
    emit(User(4, "Jan"))
}.distinctUntilChangedBy {
    it.name
}

// output
User(id=1, name=Tom)
User(id=4, name=Jan)
distinctUntilChanged

过滤用,distinctUntilChangedBy 的简化调用 。连续两个值一样,则跳过发送

val distinctUntilChanged = flow {
    emit(User(1, "Tom"))
    emit(User(1, "Tom"))

    emit(User(4, "Jan"))
    emit(User(3, "Tom"))
}.distinctUntilChanged()

// output
User(id=1, name=Tom)
User(id=4, name=Jan)
User(id=3, name=Tom)

组合操作符

combine

组合每个流最新发出的值。

private val combine1 = flowOf(1, 2)
    .onEach {
        delay(10)
    }
private val combine2 = flowOf("A", "B", "C")
    .onEach {
        delay(15)
    }
val combine = combine1.combine(combine2) { i: Int, s: String ->
    i.toString() + s
}

// output
1A
2A
2B
2C
combineTransform

合并两个流,相当于 combine + transform

private val combineTransform1 = flowOf(1, 2)
private val combineTransform2 = flowOf("A", "B", "C")
val combineTransform  = combineTransform1.combineTransform(combineTransform2) { number, text ->
    emit("$number : $text")
}

// output
1 : A
2 : A
2 : B
2 : C
merge

合并多个流成 一个流。

private val merge1 = flowOf(1, 2).onEach {
    delay(10)
}
private val merge2 = flowOf("A", "B", "C").onEach {
    delay(15)
}
val merge = merge(merge1, merge2).map {
    it.toString()
    
// output
1
A
2
B
C
flattenConcat

以顺序方式将给定的流展开为单个流 ,是Flow<Flow<T>>的扩展函数

val flattenConcat = flow {
    emit(flowOf(1, 2))
    emit(flowOf(3, 4))
}.flattenConcat()

// output
1
2
3
4
flattenMerge

作用和 flattenConcat 一样,但是可以设置并发收集流的数量。

参数 concurrency: Int ,当其 == 1时,效果和 flattenConcat 一样,大于 1 时,则是并发收集。

val flattenMerge = flow {
    emit(flowOf(1, 2).flowOn(Dispatchers.IO))
    emit(flowOf(3, 4).flowOn(Dispatchers.Default))
    emit(flowOf(5, 6))
}.flattenMerge(2)

// output
3
4
5
6
1
2
flatMapContact

这是一个组合操作符,相当于 map + flattenConcat , 通过 map 转成一个流,在通过 flattenConcat 展开合并成一个流

val flattenMapConcat = flowOf(1, 2, 3)
    .flatMapConcat {
        flowOf("$it : map")
    }
    
// output
1 : map
2 : map
3 : map
flatMapLatest

和其他 带 Latest的操作符 一样,如果下个值来了,上变换还没结束,就取消掉。内部实现: transformLatest + emitAll

val flattenMapLatest = flow {
    emit("a")
    delay(100)
    emit("b")
}.flatMapLatest { value ->
    flow {
        emit(value)
        delay(200)
        emit(value + "_last")
    }
}

// output
a
b
b_last
flatMapMerge

也是组合操作符,简化使用。 map + flattenMerge 。 因此也是有

concurrency 这样一个参数,来限制并发数。

可以并发处理数据,效率更高,所以不保证顺序

val flatMapMerge = flowOf(300, 200, 100)
    .flatMapMerge {
        flow {
            delay(it.toLong())
            emit("A:$it")
            emit("B:$it")
        }
    }
    
// output
A:100
B:100
A:200
B:200
A:300
B:300
zip

对两个流进行组合,分别从二者取值,一旦一个流结束了,那整个过程就结束了。

并行处理。

private val flowZip1 = flowOf(1, 2, 3)
private val flowZip2 = flowOf("A", "B")
val flowZip = flowZip1.zip(flowZip2) { t1, t2 ->
    t1.toString() + t2
}

// output
1A
2B

功能性操作符

接收的的时候判断 协程是否被取消 ,如果已取消,则抛出异常

cancellable
val job= flowOf(1,3,5,7).cancellable().onEach { value->
     print(value)
 } .launchIn(lifecycleScope)
 
 //取消
 job.cancel()
catch

对上游异常进行捕获 ,对下游无影响
上游 指的是 此操作符之前的流 , 下游 指的是此操作符之后的流

val catch = flow {
    emit("A")
    throw IllegalStateException()
}.catch {
    if (it is IllegalStateException) {
        emit("error")
    }
}

// output
A
error
retryWhen

有条件的进行重试 ,lambda 中有两个参数: 一个是 异常原因,一个是当前重试的 index (从0开始).

lambda 的返回值 为 Booleantrue则继续重试 ,false 则结束重试

val retryWhen = flow {
    emit("Request")
    throw IOException("network error")
}.retryWhen { cause, attempt ->
    if (attempt > 5) {
        return@retryWhen false
    }
    cause is IOException
}.catch {
    if (it is IOException) {
        emit("Request Error")
    }
}

// output

Request
//...7
Request Error

在重试超过5次之后会将异常抛出

retry

重试机制 ,当流发生异常时可以重新执行。retryWhen 的简化版。

retries: Long = Long.MAX_VALUE 指定重试次数,以及控制是否继续重试.(默认为true)

val retry = flow {
    emit("Request")
    throw IOException("network error")
}.retry(2) {
    it is IOException
}.catch {
    emit("Request Error")
}

// output
Request
//...2
Request Error
buffer

buffer 用于解决流速不均匀,指的是 Flow 上游发送数据的速度 和 Flow 下游处理数据的速度不匹配,从而可能引发的一系列问题

我们先看没有使用 buffer 的例子:

flow {
    emit(1)
    delay(1000)
    
    emit(2)
    delay(1000)
    
    emit(3)
}.onEach {
    println("$it is ready")
}.collect {
    delay(1000)
    println("$it is complete")
}

// output
1 is ready
1 is complete
2 is ready
2 is complete
3 is ready
3 is complete

默认情况下,collect函数和flow函数会运行在同一个协程当中,因此collect函数中的代码没有执行完,flow函数中的代码也会被挂起等待。

也就是说,我们在collect函数中处理数据需要花费1秒,flow函数同样就要等待1秒。collect函数处理完成数据之后,flow函数恢复运行,发现又要等待1秒,这样2秒钟就过去了才能发送下一条数据。

flow {
    emit(1)
    delay(1000)
    emit(2)
    delay(1000)
    emit(3)
}.onEach {
    println("$it is ready")
}.buffer()
    .collect {
        delay(1000)
        println("$it is complete")
    }
    
// output    
1 is ready
2 is ready
1 is complete
3 is ready
2 is complete
3 is complete

buffer函数会让 flow函数和collect函数运行在不同的协程当中,这样flow中的数据发送就不会受collect函数的影响了。

conflate

仅保留最新值, 内部就是 buffer(CONFLATED)

val conflate = flow {
    repeat(30) {
        delay(100)
        emit(it)
    }
}.conflate()
    .onEach {
        delay(1000)
    }
    
// output
0
9
19
29

输出结果不固定,仅保留最新的值

flowOn

指定上游操作的执行线程 。 想要切换执行线程 就用它!

flow.map { ... } // Will be executed in IO
 . flowOn (Dispatchers.IO) // This one takes precedence
 . collect{ ... }
 

回调操作符

onStart

在上游流开始之前被调用。 可以发出额外元素,也可以处理其他事情,比如发埋点

val onStart = flow {
    emit("A")
}.onStart {
    emit("onStart")
}

// output
onStart
A
onCompletion

在流取消或者结束时调用。可以执行发送元素,发埋点等操作

val onCompletion = flowOf("A", "B")
    .onCompletion {
        emit("Done")
    }
    
// output
A
B
Done
onEach

在上游向下游发出元素之前调用

val onEach = flow {
    emit("A")
    emit("B")
}.onEach {
    println("emit start: $it")
}

// output
emit start: A
A
emit start: B
B
onEmpty

当流完成却没有发出任何元素时回调。 可以用来兜底.。

val onEmpty = emptyFlow<Int>().onEmpty {
    emit(1)
    emit(2)
}

// output
1
2
onSubscription

SharedFlow 专属操作符 (StateFlowSharedFlow 的一种特殊实现)
在建立订阅之后 回调。 和 onStart 有些区别 ,SharedFlow 是热流,因此如果在onStart里发送值,则下游可能接收不到。

val onSubscription = MutableSharedFlow<String>().onSubscription {
    emit("subscription")
}

// output
subscription

末端操作符

collect

触发flow的运行。通常的监听方式

launch{
    flowOf(1, 2).collect{ value->
        print(value)
    }
}

// output
1
2
collectIndexed

带下标的 收集操作

flowOf("A", "B", "C")
    .collectIndexed { index, value ->
        println("$index , $value")
    }
    
// output
0 , A
1 , B
2 , C
collectLatest

collect的区别是 ,有新值发出时,如果此时上个收集尚未完成,则会取消掉上个值的收集操作
只想要最新的数据,中间值可以丢弃时可以使用此方式

flow {
    emit(1)
    delay(50)
    emit(2)
}.collectLatest { value ->
    println("Collecting $value")
    delay(100) // Emulate work
    println("$value collected")
}

// output
Collecting 1
Collecting 2
2 collected
toCollection

将结果添加到集合

val list = mutableListOf<Int>()
flow {
    emit(1)
    emit(2)
}.toCollection(list)
println(list)

// output
[1, 2]
toList

将结果转换为 List

flow {
    emit("A")
    emit("B")
}.toList().forEach { v ->
    println(v)
}
toSet

将结果转换为 Set

val set: Set<Int> = flow {
    emit(1)
    emit(2)
}.toSet()

println(set)
launchIn

直接触发流的执行,不设置 action,入参为coroutineScope 一般不会直接调用,会搭配别的操作符一起使用,如onEach,onCompletion 。返回值是Job

val launchIn = flow {
    emit("A")
}.onEach {
    println(it)
}.onCompletion {
    emit("onCompletion")
}.launchIn(viewModelScope)

// output
A
last

返回流 发出 的最后一个值 ,如果为空会抛异常

val v = flowOf("A", "B")
    .last()
rintln(v)

// output
B
lastOrNull

返回流 发出 的最后一个值 ,可以为空

val v2 = emptyFlow<Int>()
    .lastOrNull()

println(v2)
// output
null
first

返回流 发出 的第一个值 ,如果为空会抛异常

val v = flowOf("A", "B")
    .first()
println(v)

// output
A
firstOrNull

返回流 发出 的第一个值 ,可以为空

val v2 = emptyFlow<Int>()
    .firstOrNull()
println(v2)

// output
null
single

接收流发送的第一个值 ,区别于first(),如果为空或者发了不止一个值,则都会报错

val v = flowOf("A")
    .single()  // ok 
println(v)

// output
A

val v2 = flowOf("A", "B")
    .single()  // error 
println(v2)
singleOrNull

接收流发送的第一个值 ,可以为空 ,发出多值的话除第一个,后面均被置为null

val v3 = emptyFlow<Int>()
    .singleOrNull()
println(v3)

// output
null
count

返回流发送值的个数。 类似 list.size()

val v = flowOf("A", "B")
    .count()
println(v)

// output
2

val v2 = flow {
    emit(1)
    emit("A")
}.count { value ->
    value is String
}
println(v2)

// output
1
fold

从初始值开始 执行遍历,并将结果作为下个执行的 参数。

val v = flowOf("A", "B")
    .fold("Z") { initial, value -> 
        initial + value
    }
println(v)

// output
ZAB
reduce

fold 运行逻辑一致,只不过无初始值

val v = flowOf(2, 4)
    .reduce { accumulator, value ->
        accumulator * value
    }
println(v)

// output
8
Android 平台操作符
asLiveData

Flow 转换成 LiveData,用于更新数据

val asLiveData = flow {
    emit("A")
    emit("B")
}.asLiveData()

// 观察
viewModel.asLiveData.observe(this) {
    // ignore
}
asFlow

LiveData 转换成 Flow

private val userLiveData: LiveData<User> = DataRepository.getUserLiveData()

val userFlow = userLiveData.asFlow()
.map {}
.flowOn(Dispatchers.IO)
.catch {
   
}   

冷流和热流转换

shareIn

将普通flow 转化为 SharedFlow , 其有三个参数

  • scope: CoroutineScope 开始共享的协程范围
  • started: SharingStarted 控制何时开始和停止共享的策略
  • replay: Int = 0 发给 新的订阅者 的旧值数量

其中 started 有一些可选项:

  • Eagerly : 共享立即开始,永不停止
  • Lazily : 当第一个订阅者出现时, 永不停止
  • WhileSubscribed : 在第一个订阅者出现时开始共享,在最后一个订阅者消失时立即停止(默认情况下),永久保留重播缓存(默认情况下)

WhileSubscribed 具有以下可选参数:

  • stopTimeoutMillis — 配置最后一个订阅者消失到协程停止共享之间的延迟(以毫秒为单位)。 默认为零(立即停止)。
  • replayExpirationMillis - 共享的协程从停止到重新激活,这期间缓存的时效
val shareIn = flowOf(1, 2, 3)
    .shareIn(viewModelScope, SharingStarted.Eagerly, 10)
stateIn

将普通flow 转化为 StateFlow 。 其有三个参数:

  • scope - 开始共享的协程范围
  • started - 控制何时开始和停止共享的策略
  • initialValue - 状态流的初始值
val stateIn = flowOf(1)
    .stateIn(viewModelScope, SharingStarted.Lazily, 1)

参考

https://developer.android.com/kotlin/flow?hl=zh-cn

https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/-flow/

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值