一、冷流
Flow是一种类似序列的冷流,flow构建器中的代码知道流被收集的时候才运行。
惰性生成: 冷流只有在被订阅时才会开始生成数据。在订阅之前,它不会执行任何操作,也不会产生任何数据项。
简单来讲就是现学现用,什么时候使用什么时候才调用。比如使用collect就是启动的标志。
suspend fun coldFlow() = flow{
println("Flow started")
for (i in 1..3){
delay(1000)
emit(i)//用于产生元素的
}
}
@Test
fun testcoldFlow() = runBlocking {
val flow = coldFlow()
println("Starting collect...")
flow.collect{ value -> println(value)}
println("Starting collect again...")
flow.collect{ value -> println(value)}
}
运行结果可以看到,当运行到val flow = coldFlow(),这个函数并没有进行调用(没有打印Flow start),而是到调用flow.collect时才进行打印。
二、流的连续性
这很容易理解的,就是Flow收集的元素是按照顺序执行的,像水一样,先流进来就先出去,再一个关键就是这个连续性,对数据传输十分重要。
三、流的构建器
最典型的时flow 构建,除此之外还有:
四、流的上下文
就是说流的创建和收集使用同一个上下文(在同一线程里),并且不能强制更改(除非使用flowOn),例如:
没有使用flowOn:
suspend fun contextFlow1() = flow{
println("Flow started ${Thread.currentThread().name}")
for (i in 1..3){
delay(1000)
emit(i)//用于产生元素的
}
}
@Test
fun testcontextFlow1() = runBlocking {
contextFlow1().collect{
value -> println("Collected $value ${Thread.currentThread().name}")
}
}
我们可以看到,其中的都是main主线程,而且在同一上下文,但是这并不符合我们实际开发需求,有时流的构建与收集并非在同一上下文里,此时我们需要使用flowOn
suspend fun contextFlow1() = flow{
println("Flow started ${Thread.currentThread().name}")
for (i in 1..3){
delay(1000)
emit(i)//用于产生元素的
}
}.flowOn(Dispatchers.Default)
@Test
fun testcontextFlow1() = runBlocking {
contextFlow1().collect{
value -> println("Collected $value ${Thread.currentThread().name}")
}
}
这样就可以了。
五、在指定协程中收集流
就是说我们收集的流不在本线程调用了(collect),而是交给其他协程去调用,这在实际开发中也经常使用,这时要使用launchln
fun event() = (1..3)
.asFlow()
.onEach { delay(1000) }
.flowOn(Dispatchers.Default)
@Test
fun textflowLaunchIn() = runBlocking {
event().onEach { event -> println("Event: $event ${Thread.currentThread().name}" ) }
.launchIn(CoroutineScope((Dispatchers.IO)))
.join()
}
可见,这交给了后台线程去处理
六、流的取消
1.流会随着所在的协程取消而取消
2.
就是说一般的流操作可以取消的,比如使用cancel
但是呢。像asFlow这种流构建器不会执行取消操作,这时你想取消得使用cancelable
标签:fun,协程,冷流,flow,Flow,value,collect,println From: https://blog.csdn.net/weixin_63071224/article/details/137147429