美文网首页
Kotlin 协程之 Flow 详解三 还是常用操作符

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

作者: Kael_Zhang的安卓笔记 | 来源:发表于2022-09-19 15:47 被阅读0次

    机票直达

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

    概述

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

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

    • zip(常用)

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

       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
       }
    
    • merge(常用)

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

       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 组合每个流最新发出的值,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(常用)

    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
     }
    
    • flattenMerge

    和 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 ,顺序不固定,有并发
     }
    
    • flatMapLatest

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

    • flatMapContact

    flattenConcat + map

    回调操作符

    • onStart、onCompletion(常用)

    开始和结束

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

    *onEmpty

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

    • onEach

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

    线程调度操作符

    • flowOn(常用)

    用于将上游的流切换到指定协程上下文的调度器中执行,同时不会把协程上下文暴露给下游的流,即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) //主线程
      }
    }
    

    功能性操作符

    • catch (常用)

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

    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") 抛出异常以后 没有继续发送
    
    • retryWhen

    有条件的进行重试 ,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次
    

    相关文章

      网友评论

          本文标题:Kotlin 协程之 Flow 详解三 还是常用操作符

          本文链接:https://www.haomeiwen.com/subject/kekportx.html