Channel的源代碼如下:
public interface Channel<E> : SendChannel<E>, ReceiveChannel<E> {
...
}
- Channel的父類有發送消息的SendChannel和接受消息的ReceiveChannel,Channel分爲有緩衝區和無緩衝區,無緩衝的通道在發送者和接收者相遇時傳輸元素。如果發送先被調用,則它將被掛起直到接收被調用, 如果接收先被調用,它將被掛起直到發送被調用。Channel() 工廠函數與 produce和actor 建造器通過一個可選的參數 capacity 來指定 緩衝區大小 。緩衝允許發送者在被掛起前發送多個元素, 就像 BlockingQueue 有指定的容量一樣,當緩衝區被佔滿的時候將會引起阻塞。
Channel的構建
-
GlobalScope 中提供2個函數 produce() 和 actor()
- produce()函數返回值是一個ReceiveChannel對象,最後一個參數是一個繼承SendChannel的對象,使用代碼如下:
val data = GlobalScope.produce<String> { send("a") }.receive()
- actor()函數的最後一個參數是一個繼承ActorScope類的對象,ActorScope類繼承了ReceiveChannel類,用來接受處理函數返回一個SendChannel對象發送的消息,使用代碼如下:
GlobalScope.actor<String> { val data = receive() }.send("a")
produce()和actor()第二個參數capacity 默認值是0,表示構建的channel是無緩衝區的,若重新賦值爲大約0,則構建的channel是有緩衝區的。
- 使用標準庫中的iterator()函數構建一個相似的管道,使用 iterator 替換 produce、yield 替換 send、next 替換 receive、 Iterator 替換 ReceiveChannel 來擺脫協程作用域,你將不再需要 runBlocking。代碼如下:
iterator<String> { yield("ss") }.next()
- 直接初始化,send()和receive()函數是掛起函數,只能在協程或者其他掛起函數中調用。代碼如下:
GlobalScope.launch { val channel = Channel<String>() channel.send("11") val data = channel.receive() }
**Channel()參數capacity 默認值是0,表示構建的channel是無緩衝區的,若重新賦值爲大約0,則構建的channel是有緩衝區的。**
-
計時器Channel-- ticker (),使用代碼如下:
GlobalScope.launch(Dispatchers.Main) {
val tickerChannle = ticker(1,
initialDelayMillis = 0)
tickerChannle.receive()
tickerChannle.cancel()
}
使用Channel 實現View 防止重複點擊
fun View.setOnceClick(block: suspend () -> Unit) {
val action = GlobalScope.actor<Unit> {
for (event in channel){
block()
delay(2000)//延遲2s
}
}
setOnClickListener {
action.offer(Unit)
}
}
- 在View 類中擴展一個函數setOnceClick(),在該函數中調用View的點擊事件函數, GlobalScope.actor()函數返回一個SendChannel 對象,在點擊事件中調用offer()函數,發送消息。
- actor()函數的最後一個參數是一個繼承ActorScope類的對象,ActorScope類繼承了ReceiveChannel類,用來接受處理函數返回一個SendChannel對象發送的消息