kotlin Flow 学习指南(一)

前言

学过kotlin的同学知道,协程的挂起函数可以异步的返回单个值,但是该如何异步返回多个计算好的值呢,这就是Flow异步数据流的用武之地。但是Flow不仅仅于此,更形象的说,Flow是RxJava,kotlin版本的实现。

官方定义

我们可以从Android官网,Flow定义:在协程中,与仅返回单个值的挂起函数相反,数据流可按顺序发出多个值。例如,我们可以通过数据流从数据库中实时接收更新。数据流使用挂起函数通过异步方式生成和使用值,也就是说,数据流可安全地发出网络请求以生成下一个值,而不会阻塞主线程。

开始使用

概念都是晦涩难懂的,我们直接看个简单例子:
首先我们gradle引入Flow相关包,由于Flow是基于协程基础开发,引入协程相关包就行:

implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.1")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.1")

这里我们实现一个简单的计时器,数据我们使用ViewModel,创建一个简单的数据流。

class MainViewModel : ViewModel() {

    val timeFlow = flow {
        var time = 0
        while (true) {
            emit(time)
            delay(1000)
            time++
        }
    }
}

上面简单定义一个冷流Flow,每隔一秒钟time加一,冷流是什么呢,就是需要收集才会发射数据流,后面会介绍热流。布局方面,我们使用Jetpack Compose实现:

@Preview(showBackground = true)
@Composable
fun Content() {
    val viewModel: MainViewModel = viewModel()
    var times by remember { mutableStateOf(0) }
    // 获取LifecycleOwner
    val lifecycleOwner = LocalLifecycleOwner.current

    Column(
        Modifier
            .fillMaxSize()
            .wrapContentSize(Alignment.Center)
    ) {
        Text(
            textAlign = TextAlign.Center,
            modifier = Modifier.width(200.dp),
            text = "$times",
            color = Color.Blue,
            fontSize = 26.sp
        )

        Button(
            onClick = {
                lifecycleOwner.lifecycleScope.launch {
                    viewModel.timeFlow.collect { time ->
                        times = time
                    }
                }
            },
            modifier = Modifier.width(200.dp)
        ) {
            Text(
                textAlign = TextAlign.Center,
                text = "START",
                color = Color.White,
                fontSize = 20.sp
            )
        }
    }
}

上面代码就是一个垂直布局,Text来接收显示计时器的数值,Button用来启动协程,收集数据流,并改变times的值,times是remember包装的变量,会根据值变化,通知Content函数重组并刷新UI。
实际效果如下:
times1
点击按钮开始时,计时器从0开始,每隔一秒,数字改变一下,相当于一个秒表。
我们改变一下接收数据流的地方:

lifecycleOwner.lifecycleScope.launch {
    viewModel.timeFlow.collect { time ->
        times = time
        delay(3000)
    }
}

每次collect后,delay 3秒,看下效果:
times2

我们可以看到隔了3秒,才改变一次数值,跟我们要求的秒表效果不一致,这是收集的流和发射的流速度不一致导致的,接收的值都是旧值。我们收集流方法collect改成collectLatest试下:

times3

我们可以看到,数值变化效果正常了,collectLatest看函数名称就知道,收集最新的数据,上一次数据没有处理完,直接丢弃。

总结

至此,我们从一个简单的例子,了解了Flow基本使用方法,Flow用法远不止于此,下篇我们介绍一下,Flow的常见操作符。
创作不易,喜欢的麻烦点赞、评论,以资鼓励。

  • 9
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值