一、冷流

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

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐