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 1623123193526consumeEach 會在接收到數據后,從把數據從隊列中移除。其他接收者,就不會再次接收了。也就是同一個數據,只能被一個數據接收
遍歷
kotlin 為我們提供了一個簡單的 channel 的遍歷方法,也就是 for 循環。
遍歷 channel 會一直處于掛起狀態,只要有數據,就會全部遍歷一次。沒有數據,處于掛起狀態。
close
不同于Queue,channel可以被關閉,對于channel的關閉,我們可以使用close(),關閉前發射的值將仍然能在接收端收到,接收端通過for循環來遍歷接收到的值。
如果執行了 close 以后,還調用 send 方法,就會崩潰
所以一種比較安全的做法是,在 send 之前,要判斷一下channel 是否已經關閉了
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的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Kotlin实战指南二十:flow
- 下一篇: Android 监听APP进入前台、后台