Android Coroutines Channels
转载请标明出处:http://blog.csdn.net/zhaoyanjun6/article/details/117674222
本文出自【赵彦军的博客】
文章目录
- 依赖
- channels 可以干啥
- 数据模型
- Channel的特点
- Channel 分类
- receive
- consumeEach
- 遍历
- close
- Channel的协程Buidler(SendChannel / ReceiveChannel)
- BroadcastChannel
- Select
- 其他方法
依赖
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1'
channels 可以干啥
channels
用于协程间的通信, 允许我们在不同的协程间传递数据(a stream of values).
数据模型
生产者-消费者模式
发送数据到channel
的协程被称为producer
, 从channel
接受数据的协程被称为consumer
.
当需要的时候, 多个协程可以向同一个channel
发送数据, 一个channel
的数据也可以被多个协程接收.
当多个协程从同一个channel
接收数据的时候, 每个元素仅被其中一个consumer
消费一次. 处理元素会自动将其从channel
里删除.
Channel的特点
Channel
在概念上有点类似于BlockingQueue
, 元素从一端被加入, 从另一端被消费. 关键的区别在于, 读写的方法不是blocking
的, 而是suspending
的.
在为空或为满时. channel
可以suspend它的send
和receive
操作.
生成数据,消费数据的方法都需要在协程里执行
Channel 分类
- RENDEZVOUS :表示约会形式的等待,没有缓存使用,send调用后就会一直挂起,直到receive到达。也是 Channel 默认形式。
- UNLIMITED:表示执行缓存无限容量,容量是
Int.MAX_VALUE
,send调用后就存放在channel里直接返回,不管是否有receive。但是我们在使用时还是需要注意内存情况。 - CONFLATED:表示保留最新,send调用后就存放在channel里直接返回,但是channel里只能存放最近一次 send 的值。
- BUFFERED:表示执行缓存使用默认容量,默认是64。
receive
在 Channel
有数据时接收数据,在 Channel
为空时处于挂起状态,时刻准备接收数据。一旦接收完数据后,就执行完了
class MainActivity : AppCompatActivity() {private val channel = Channel<String>()override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)findViewById<View>(R.id.btn1).setOnClickListener {//发送数据GlobalScope.launch {channel.send("item1 ${System.currentTimeMillis()}")}}//接收数据GlobalScope.launch {repeat(10) {Log.d("channel", "receive--${channel.receive()}")}}}
consumeEach
class MainActivity : AppCompatActivity() {private val channel = Channel<String>()override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)findViewById<View>(R.id.btn1).setOnClickListener {//发送数据GlobalScope.launch {channel.send("item1 ${System.currentTimeMillis()}")}}//接收数据GlobalScope.launch {channel.consumeEach {Log.d("channel", "consumeEach--${it}")}}}
}//输出结果
D/channel: consumeEach--item1 1623123193526
consumeEach
会在接收到数据后,从把数据从队列中移除。其他接收者,就不会再次接收了。也就是同一个数据,只能被一个数据接收
遍历
kotlin
为我们提供了一个简单的 channel
的遍历方法,也就是 for
循环。
遍历 channel
会一直处于挂起状态,只要有数据,就会全部遍历一次。没有数据,处于挂起状态。
class MainActivity : AppCompatActivity() {private val channel = Channel<String>()override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)findViewById<View>(R.id.btn1).setOnClickListener {//发送数据GlobalScope.launch {repeat(100) {channel.send("item1 $it")}}}//接收数据GlobalScope.launch {for (i in channel) {Log.d("channel", "$i")}}}
}
close
不同于Queue
,channel
可以被关闭,对于channel
的关闭,我们可以使用close()
,关闭前发射的值将仍然能在接收端收到,接收端通过for
循环来遍历接收到的值。
如果执行了 close 以后,还调用 send 方法,就会崩溃
所以一种比较安全的做法是,在 send
之前,要判断一下channel
是否已经关闭了
//发送数据
GlobalScope.launch {if (!channel.isClosedForSend) {channel.send("item1 ${System.currentTimeMillis()}")}
}
Channel的协程Buidler(SendChannel / ReceiveChannel)
我们在上面示例中可见,通过一个生产者协程producer和一个消费者协程consumer进行了数据的send和receive,而在官方框架中也专门为生产者协程和消费者协程提供了两个函数来构建出协程,它们就是produce和actor。
而且通过produce和actor函数启动的协程结束后都会自动关闭对应的Channel。
produce:启动一个生产者协程,返回ReceiveChannel。
actor:启动一个消息者协程,返回SendChannel(注意,actor函数目前框架中是被标为废弃)。
示例如下:
BroadcastChannel
前面介绍的Channel的所发送的数据只能被一个消费者消费,而如果需要一对多的话那就需要BroadcastChannel,它会像我们平时使用广播一样进行分发给所有订阅者。
另外需要注意的是,BroadcastChannel不支持RENDEZVOUS。
Select
Select一般是IO多路复用的概念,而在协程的Select则是用于挂起函数的多路复用。通俗一点表达就是可以同时进行多个挂起函数的调用,但最后只选择执行最快的挂起函数的返回结果。
其他方法
channel.isClosedForSend //发送通道是否关闭
channel.isClosedForReceive //接收通道是否关闭
channel.isEmpty //是否为空
Android Coroutines Channels相关推荐
- Android Kotlin Exception处理
转载请标明出处:http://blog.csdn.net/zhaoyanjun6/article/details/118386817 本文出自[赵彦军的博客] 往期精彩文章 Android Corou ...
- Android Kotlin 协程async
转载请标明出处:http://blog.csdn.net/zhaoyanjun6/article/details/118093646 本文出自[赵彦军的博客] 往期精彩文章 Android Corou ...
- Android Kotlin协程和Retrofit结合使用
转载请标明出处:http://blog.csdn.net/zhaoyanjun6/article/details/118085035 本文出自[赵彦军的博客] 往期精彩文章: Kotlin实战指南二十 ...
- 携程机票 Android Jetpack 与 Kotlin Coroutines 实践 | 开发者说·DTalk
本文原作者: 禹昂,携程机票移动端资深工程师,Kotlin 中文社区核心成员,图书<Kotlin 编程实践>译者. 原文发布于: 携程技术 https://mp.weixin.qq.com ...
- 干货 | 携程机票 Android Jetpack 与 Kotlin Coroutines 实践
作者简介 禹昂,携程机票移动端资深工程师,Kotlin 中文社区核心成员,图书<Kotlin 编程实践>译者. 一.前言 1.1 技术背景与选型 自 2017年 Google IO 大会以 ...
- 【译】如何在 Android 中使用 Retrofit, Moshi, Coroutines Recycler View
翻译说明: 原标题: How-To: Retrofit, Moshi, Coroutines & Recycler View for REST Web Service Operations w ...
- android新架构模式_Android MVIReact架构模式
android新架构模式 If you are already aware of basic principles of architecture patterns and MVVM and MVI ...
- android——消息总线(Eventbus、FlowBus)
前言 消息总线又叫事件总线,**为什么我们需要一个消息总线呢?**是因为随着项目变大,页面变多,我们可能出现跨页面.跨组件.跨线程.跨进程传递消息与数据,为了更方便的直接通知到指定的页面实现具体的逻辑 ...
- 6、通道(Channels)
本节介绍通道----Channels(官方文档) Deferred values提供了一种在协程之间传递单个值的简便方式,通道(channels)则提供了在协程间传递流的方法. 1.Channel b ...
最新文章
- 如何利用 notedown 完成 ipynb与markdown之间的格式转换?
- 更好的内存管理-jemalloc (redis 默认使用的)
- python性能优化之函数执行时间分析_python性能优化之函数执行时间分析
- 一个服务器9个角色的体验,谁体验过?剑网三缘起服务器合并
- Eclipse没有server 配置Tomcat
- isfile java_isfile 方法
- 实例6:python
- base64 golang 图片_golang基础学习-base64使用
- 分享思路:Python+Spark爬虫音乐推荐系统 音乐数据分析可视化 音乐推荐app 音乐网站 大数据毕业设计(app+web+爬虫+spark+可视化)
- 除了Office和wps,还有什么办公软件比较好用?
- Web程序设计大作业
- 计算机竞赛奖学金申请书,计算机专业奖学金申请书
- journey、voyage、trip、tour、travel的用法区别
- Android集合之SparseArray、ArrayMap详解
- 基础算法:斐波那契函数学习
- 蔬菜小程序服务器,生鲜蔬菜同城配送小程序案例分析
- 一个简单的例子解释什么是量子计算机
- CPU个数、CPU核心数、CPU线程数
- 金蝶KIS商贸版实现'条码标签打印'功能进行商品条码打印
- 天池大赛o2o优惠券第一名代码解读(1)
热门文章
- java核心api_Java核心API之字符流使用介绍
- processing python模式添加图片_processing学习整理---Image
- java project 部署_关于Java Project项目在Linux下部署步骤及注意事项
- Centos7搭建Kubernetes集群
- 隐马尔科夫模型 概念(上)
- 信息抽取新SOTA!首个结构化生成式信息抽取预训练模型,一统信息抽取四大任务...
- NeurIPS 2020有哪些值得读的「图神经网络」论文?
- BERT-of-Theseus:基于模块替换的模型压缩方法
- 经典论文复现 | ICML 2017大热论文:Wasserstein GAN
- 【建议收藏】HTTP与HTTPS的区别