Android面试指南—Kotlin Flow篇

本文详细介绍了Kotlin Flow的基本概念、工作原理、与RxJava的对比、并发处理、异常处理、重试策略,以及Cold Flow和Hot Flow的区别。通过对StateFlow和SharedFlow的探讨,帮助理解何时在Android开发中选择使用它们。
摘要由CSDN通过智能技术生成
什么是 Kotlin Flow流?

在Kotlin官网中定义中是这么说的:

在协程中,与仅返回单个值的挂起函数相反,Flow可按顺序发出多个值, 它以协程为基础构建,可提供多个值,从概念上来讲,Flow是可通过异步方式进行计算处理的一组数据序列,所发出值的类型必须相同。

总结一下,我们可以将Flow定义为具有多个异步计算值的协程。它是可以异步计算的数据流,用于按顺序发送多个值。 发出的数据必须是同一类型,并且也是按顺序发出的,Flow使用挂起的函数以异步方式消费和生产。

为什么需要Kotlin Flow?

为了使应用程序响应并提高其性能,异步编程起着非常重要的作用,日常开发中,在协程没有出现的岁月里,可以使用RxJava响应式编程框架,它是ReactiveX基于Java的扩展,直到Kotlin的出现和发展。

在Kotlin中,相同的功能以Kotlin Flow API的形式提供。它不仅具备所需的所有运算符和功能,而且还支持挂起函数,这有助于以顺序方式执行异步任务,也让代码变得更加简洁和高效。

如果我们有 RxJava/其他响应式实现,为什么要创建 Flow?

在Flow中,如果我们想转换数据,用一个map操作符即可,这与RxJava有些不同,RxJava具有同步的map和异步的latMapSingle。流程图运算符有一个lambda,它是一个暂停,因此它适用于同步和异步。过滤数据也是如此,Flow只有一个Filter运算符适用于两者。

所以Flow能有效减少了在其它响应式实现中引入的操作符,更加方便简洁,这也是为什么要使用Flow的重要原因。

Kotlin Flow 是如何工作的?

平常我们开发都会使用到网络请求吧,当从服务器请求数据并使用异步编程来处理该数据时,Flow会在后台线程中异步管理该数据,因为某些进程可能会运行更长时间来获取数据。一旦收集器接收并收集了数据,就会使用回收器视图显示数据。

在这里插入图片描述

我们已经知道,Flow是一系列值,它使用挂起函数异步生成和使用值。

Flow流由三个实体组成:

  • 生产者: 用于发出添加到流中的数据。
  • 中介:它可以修改发送到流中的值
  • 消费者 : 从流中接收值
Flow builders 的几种类型?

我们平时创建一个Flow流一般提供了4种方式

  • flowOf:它用于一组数据的创建Flow流

    flowOf(4, 2, 3, 45, 5)
                .collect {
         
                    print(it)
                }
  • asFlow:这是一个扩展函数,有助于将当前类型转换为Flow流

    (1..5).asFlow()
                .collect {
         
                    print(it)
                }
    
    
  • flow:这就是官方示例程序标准的创建Flow流的方式

    flow {
         
                (0..10).forEach {
         
                    emit(it)
                }
            }.collect {
         
                print(it)
            }
    
    
  • channelFlow:此构建器使用构建器本身提供的发送元素来创建Flow流。

    @OptIn(ExperimentalCoroutinesApi::class)
            channelFlow {
         
                (0..10).forEach {
         
                    send(it)
                }
            }.collect {
         
                print(it)
            }
    
    

    需要注意的是channelFlow这个Api还是实验性的,所以正式项目环境中很少用到

Kotlin Flow如何实现并发?

我们都知道,Flow是异步的,但是收集器collect和发射器emit是按顺序的方式来工作,怎么说呢?就是当收集器开始收集数据,然后发射器发射出数据,直到没有发射器为止。经常有人说,它就是用同步的代码做异步的事情,这个总结挺到位的。当然,为了实现Flow并发,我们必须从使用单个协程转变为使用多个协程。

Flow对此提供了一些特殊的并发运算符,比如说buffer(),简单使用一个例子

fun main() = runBlocking {
   
    val time = measureTimeMillis {
   
        flow {
   
            for (i in 1..5) {
   
                delay(100)
                emit(i)
            }
        }
        .buffer()
        .collect {
    value ->
            delay(300)
            println(value)
        }
    }
    println("Collected in $time ms")
}

在上述例子中,所有的 delay 所花费的时间是2000ms,当然这是在没有并发操作的情况下,然而通过buffer操作符并发地执行emit,再顺序地执行collect函数后,所花费的时间在1700ms左右,比预期的花费时间更高效。

那我们使用缓存区buffer的时候会发生什么呢?如下图所示

在这里插入图片描述

当收集器处理发出的数据时,下一个发射器开始其过程。它不会等待收集器完成它对先前发出的数据的处理并返回控制权。这是通过在单独的协程中运行收集器和发射器来实现的,这与在单个协程中运行的异步顺序方法不同。在内部它使用通道Channel将数据发送给接收者。

Kotlin Flow 如何进行并行调用?

那有小伙伴说了,如果我有很多个长任务想要同时执行呢,也就是并行,Flow能不能做到呢?答案肯定是YES的,为了并行运行长任务,我们需要使用Flow提供的组合操作符zip,它通过指定的函数将两个流集合的排放组合在一起,并根据此函数的结果为每个组合排放单个项目。

让我们通过示例代码来理解弹珠图:

val flowOne = flowOf(1, 2, 3)
val flowTwo = flowOf("A", "B", "C")
​
flowOne.zip(flowTwo) {
    intValue, stringValue ->
    "$
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值