参考
- https://github.com/Kotlin/kotlinx.coroutines/blob/master/coroutines-guide.md
- https://github.com/Kotlin/kotlinx.coroutines/blob/master/ui/coroutines-guide-ui.md
Channelの基本
Channelの種類
クラス名 | 説明 |
---|---|
Channel | Channelのレシーバーが一つの場合に使用する。 |
BroadcastChannel | Channelのレシーバーが複数存在する場合に使用する。 |
Channelの要素を追加する方法
メソッド名 | 説明 |
---|---|
send() | |
offer() | suspendファンクション外で要素を追加する。 |
Channelの要素を消費する方法
動作確認コード
class MainActivity : AppCompatActivity(), AnkoLogger {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
test1()
test2()
test3()
test3a()
test4()
test4a()
test5()
test5a()
}
/**
* receive()の後にsend()を呼び出した場合
*
* 実行ログ: 無し(receiveでブロックされるため、channel1.sendまで処理が進まない。)
*/
private fun test1() {
val channel = Channel<Int>()
launch(UI) {
val result = channel.receive()
info("test1: ${result}")
channel.send(1)
}
}
/**
* receive()とsend()を別のコルーチンで実行した場合
*
* 実行ログ:
* test2: 1
*/
private fun test2() {
val channel = Channel<Int>()
launch(UI) {
val result = channel.receive()
info("test2: ${result}")
}
launch(UI) {
channel.send(1)
}
}
/**
* 複数のコルーチンで一つのchannelをreceive()した場合
*
* 実行ログ:
* test3-1: 1
* test3-2: 2
*/
private fun test3() {
val channel = Channel<Int>()
launch(UI) {
val result = channel.receive()
info("test3-1: ${result}")
}
launch(UI) {
val result = channel.receive()
info("test3-2: ${result}")
}
launch(UI) {
channel.send(1)
channel.send(2)
channel.send(3)
}
}
/**
* test3をBroadcastChannelにした場合
*
* 実行ログ:
* test3a-1: 1
* test3a-2: 1
*/
private fun test3a() {
val channel = BroadcastChannel<Int>(10)
launch(UI) {
val result = channel.openSubscription().receive()
info("test3a-1: ${result}")
}
launch(UI) {
val result = channel.openSubscription().receive()
info("test3a-2: ${result}")
}
launch(UI) {
channel.send(1)
channel.send(2)
}
}
/**
* 複数のコルーチンで一つのchannelをselectした場合
*
* 実行ログ:
* test4-1: 1
* test4-2: 2
*/
private fun test4() {
val channel = Channel<Int>()
launch(UI) {
select<Unit> {
channel.onReceive { value -> // this is the first select clause
info("test4-1: ${value}")
}
}
}
launch(UI) {
select<Unit> {
channel.onReceive { value ->
info("test4-2: ${value}")
}
}
}
launch(UI) {
channel.send(1)
channel.send(2)
}
}
/**
* test4をBroadcastChannelにした場合
*
* 実行ログ:
* test4a-1: 1
* test4a-2: 1
*/
private fun test4a() {
val channel = BroadcastChannel<Int>(10)
launch(UI) {
select<Unit> {
channel.openSubscription().onReceive { value ->
info("test4a-1: ${value}")
}
}
}
launch(UI) {
select<Unit> {
channel.openSubscription().onReceive { value ->
info("test4a-2: ${value}")
}
}
}
launch(UI) {
channel.send(1)
channel.send(2)
}
}
/**
* 複数のコルーチンで一つの channel を consumeEach した場合
*
* 実行ログ:
* test5-1: 1
* test5-2: 2
*/
private fun test5() {
val channel = Channel<Int>()
launch(UI) {
channel.consumeEach {
info("test5-1: ${it}")
}
}
launch(UI) {
channel.consumeEach {
info("test5-2: ${it}")
}
}
launch(UI) {
channel.send(1)
channel.send(2)
}
}
/**
* test5をBroadcastChannelにした場合
*
* 実行ログ:
* test5a-1: 1
* test5a-1: 2
* test5a-2: 1
* test5a-2: 2
*/
private fun test5a() {
val channel = BroadcastChannel<Int>(10)
launch(UI) {
channel.consumeEach {
info("test5a-1: ${it}")
}
}
launch(UI) {
channel.consumeEach {
info("test5a-2: ${it}")
}
}
launch(UI) {
channel.send(1)
channel.send(2)
}
}
}