Android Kotlin协程间的通信Channel介绍

学更好的别人,

做更好的自己。

——《微卡智享》

150344580f91400687dd83208f0e27d7.png

本文长度为2399,预计阅读7分钟

前言

使用Kotlin做Android项目时,肯定少不了使用协程,而在协程的使用中,少不了要在不同的协程中传递数据,而Kotlin中的Channel,就是专门用来处理协程之间的通信,今天这篇就是来看看Channel的用法。

def984dc31987fba5098e4abbc84c5a2.png

Channel简介

03f3ee6cab5bfab1440d435db378b140.png

微卡智享

channel用于协程间的通信, 允许我们在不同的协程间传递数据。channel非常类似于一个 java 中非常常见的概念BlockingQueue,元素从一端被加入, 从另一端被消费.。当需要的时候, 多个协程可以向同一个channel发送数据, 一个channel的数据也可以被多个协程接收。当多个协程从同一个channel接收数据的时候, 每个元素仅被其中一个consumer消费一次. 处理元素会自动将其从channel里删除。

微卡智享

Channel的用法

channel可以简单的通过send和receive实现。

fun main() = runBlocking{
    val intchannel = Channel<Int>()
    launch {
        for(x in 1..10) intchannel.send(x)
    }


    repeat(10){ 
        val recv = intchannel.receive()
        println("read:$recv")
    }
}

cff2ab4f8096e30d5b8f0c5bac0b86ba.png

输出结果

channel还可以通过遍历来实现receive。

fun main() = runBlocking{
    val intchannel = Channel<Int>()
    launch {
        for(x in 1..6) intchannel.send(x)
    }


    for(recv in intchannel) println("read:$recv")
    println("receive finish")
}

88b3316d482e9592163685fca10276d0.png

输出结果

从上图中可以看到,通过for的方式可以直接赋值到recv里打印出来了,但是在代码的结尾中我们的println("receive finish"),并没有在控制台打印出来,程序也没有退出,这是因为接收者在协程中还一直在等待。

想要正常结束并退出,接下来就要用到channel的关闭了,Channel可以被关闭, 说明没有更多的元素了。取消协程也会关闭channel。那我们改一下上面的代码,加上close。

fun main() = runBlocking{
    val intchannel = Channel<Int>()
    launch {
        for(x in 1..6) intchannel.send(x)
        intchannel.close()
    }


    for(recv in intchannel) println("read:$recv")
    println("receive finish")
}

af13f0b651253bba1d64e2de173b4bae.png

代码中加入了close后,可以看到,channel接收完后,打印出的finish并且退出程序了。
 

微卡智享

channel的类型

Channel有四种不同的类型,类型间不同的区别有两点,一是定义内部可以存储的元素,二是Send方式是否可以被挂起;而所有channel类型的Receive方法都是同样的行为,如果channel不为空, 接收一个元素, 否则挂起,具体的类型如下:

  1. Rendezvous channel(默认类型): 0尺寸buffer,Send和Receive要见面,否则Send挂起,就是说每Send完的后,如果一直没有Receive,即被挂起。

  2. Buffered channel:指定元素大小,当满了后Send会被挂起。

  3. Conflated channel: 新元素会覆盖旧元素,receiver只会得到最新元素,Send永不挂起。

  4. Unlimited channel: 无限元素,Send不被挂起。

接下来我们做个用多个协程向同一个Channel发送数据的例子来看看这四种模式。

01

Rendezvous channel(默认类型)

fun main() {
    val channel = Channel<String>()
    runBlocking {
        val res1 = async {
            for (x in 1..5) {
                channel.send("I am $x")
            }
            return@async "res1 over"
        }
        val res2 = async {
            for (y in 11..15) {
                channel.send("you are $y")
            }
            return@async "res2 over"
        }
        val res3 = async {
            for (z in 21..25) {
                channel.send("he is $z")
            }
            return@async "res3 over"
        }
        launch {
            println(" async finish ${res1.await() + res2.await() + res3.await()} ")
            channel.close()
        }
        for (item in channel) {
            println(item)
        }


        println("finish")
    }
}

代码中用async开启三个协程,当三个协程执行完后,关闭channel。下面是输出结果。

d6ec2a19c0a76dcd2216592d47542955.png

02

Buffered channel

val channel = Channel<String>(3)

当channel中后面加上数字3,然后再运行看。

575d469859bad86f273265c8d3c40809.png

上图中,因为满了3个后Send挂起,所以第一个协程(1-5)完后,第二个协程的11数字进去后也开始挂起了,这时的挂起也让第三个协程(21-25)的第一条进入到队列中。

03

Conflated channel

val channel = Channel<String>(Channel.CONFLATED)

当channel中后面参数加上Channel.CONFLATED,然后再运行看。

e6850db117fa3de2f574cde011a6c74d.png

可以看到输出的只有两条,第一条数据和最后一条数据。

04

Unlimited channel

val channel = Channel<String>(Channel.UNLIMITED)

当channel中后面参数加上Channel.UNLIMITED,然后再运行看。

4f2c5f161a98b085a7d285a2b4292e4b.png

这里就可以看出,当使用Channel.UNLIMITED时,完全是按钮协程调用的顺序输出的。

Kotlin使用协程时,还是会经常用Channel来处理协程之间的数据通信,更多的用法可以自己去多做尝试

968d45c535cd741368302d237d1ceb48.png

b40efddbea055b4976722886b5e08e9f.png

往期精彩回顾

 

073a6f02449e1e7ef8a3ba558da453b6.png

Android内存篇(三)----自动重启APP实现内存兜底策略

 

 

ab8f4d7bb7a9335570f369c895b135bc.png

Android内存篇(二)---JVMTI在Anroid8.1下的使用

 

 

be87206b3acdd5840f21c56727982ff4.png

Android内存篇(一)---使用JVMTI监控应用

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Vaccae

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值