Kotlin 协程之 Flow 详解三 还是常用操作符

2022-09-19  本文已影响0人  Kael_Zhang的安卓笔记

机票直达

Kotlin 协程之 Flow 详解一 冷流的生产和消费
Kotlin 协程之 Flow 详解二 常用操作符
Kotlin 协程之 Flow 详解三 还是常用操作符

概述

Flow类似RxJava,当然也有许多操作符,不过Flow的操作符学习要比RxJava的操作符简单直白一些,本人感觉更喜欢Flow一些,本文将介绍一部分中间操作符的使用(合并、回调、线程调度)

合并操作符(属于中间操作符)

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

   val flow1  = listOf(0,1,2,3,4,5).asFlow() // zip后, 5将被丢弃
   val flow2 = listOf(6,7,8,9,10).asFlow()
   flow1.zip(flow2){value1,value2->
       "it is $value1,$value2"
   }.collect {
      println(it) //结果 it is 06 、17、 28、 39、410
   }

是将两个流合并起来,将每个值依次发出来

   val flow1  = listOf(0,1,2,3,4,5).asFlow()
   val flow2 = listOf(6,7,8,9,10).asFlow()
   merge(flow1,flow2).collect {
      println(it) //结果 0,1,2,3,4,5,6,7,8,9,10
   }

combine 组合每个流最新发出的值,combineTransform = combine+Transform

val flow1 = flowOf(1, 2).onEach { delay(100) }
val flow2 = flowOf("3", "4", "5").onEach { delay(150) }
flow1.combine(flow2) { value1, value2 ->
 "$value1,$value2"
 }.collect {
  println(it)  // 结果 13  23  24 25"
}

flattenConcat 展平多个流,以顺序方式将给定的流展开为单个流

flow {
    emit(flowOf(1, 2, 3,4,5))
    emit(flowOf(6,7,8,9,10))
 } .flattenConcat().collect {
     println(it) //结果 1,2,3,4,5,6,7,8,9,10
 }

和 flattenConcat 大抵一样,区别是可以设置并发数

flow {
    emit(flowOf(1, 2, 3,4,5))
    emit(flowOf(6,7,8,9,10))
 } .flattenMerge(2).collect {
     println(it) //结果 1,2,3,4,5,6,7,8,9,10 ,顺序不固定,有并发
 }

和其他Lastest操作符一样,来不及转换时就取消

flattenConcat + map

回调操作符

开始和结束

flow {
    emit(1)
    emit("2")
    emit("3")
}.onStart {
    println("onStart")
}.onCompletion {
    println("onCompletion")
}.collect {
    println(it)
}
// 结果 onStart 1 2 3 onCompletion

*onEmpty

在flow为空的时候会回调,很好理解,不再示例

是在每次collect之前调用,很好理解,不再示例

线程调度操作符

用于将上游的流切换到指定协程上下文的调度器中执行,同时不会把协程上下文暴露给下游的流,即flowOn方法中协程上下文的调度器不会对下游的流生效

launch(Dispatchers.Main) {
  flow {
    emit(1) // IO线程
    emit(2) // IO线程
    emit(3) // IO线程
  }.flowOn(Dispatchers.IO).map {
    "it is $it" // Default线程
  }.flowOn(Dispatchers.Default).collect {
    println(it) //主线程
  }
}

功能性操作符

异常处理,也可以重新发送一个值

flow {
    emit(1)
    throw IllegalArgumentException("exception")
    emit("3")
}.onStart {
    println("onStart")
}.catch{
    println("exception")
    emit(2)
}.onCompletion {
    println("onCompletion")
}.collect {
    println(it)
}
// 结果 onStart 1 exception 2  onCompletion
// emit("3") 抛出异常以后 没有继续发送

有条件的进行重试 ,lambda 中有两个参数: 一个是 异常原因,一个是当前重试的 index (从0开始)。
lambda 的返回值 为 Boolean ,true则继续重试 ,false 则结束重试。

flow<Int> {
    throw IOException("error")
 } .retryWhen {cause,attempt->
     if(attempt > 3){
        return@retryWhen false
     }
    cause is IOException
 }
//结果将retry 3次
上一篇下一篇

猜你喜欢

热点阅读