1. AtsushiUemura

    Posted

    AtsushiUemura
Changes in title
+【Kotlin】Coroutineを理解する
Changes in tags
Changes in body
Source | HTML | Preview
@@ -0,0 +1,229 @@
+#はじめに
+Kotlin 1.1からCoroutineが実験的に組み込まれました。
+Coroutineとは**「特定のスレッドに束縛されない、中断可能な計算インスタンス」**です。
+非同期処理で用いられますが、`Thread`よりも軽量で、実行途中で処理を`中断・再開`することができます。
+
+#準備
+Coroutineを利用するために、`build.gradle`に下記の情報を追記します。
+今回は2018/09/29時点での最新版(0.30.0)を使用しています。
+更新状況は[ここ](https://github.com/Kotlin/kotlinx.coroutines/releases)から確認できます。
+
+```gradle:build.gradle
+dependencies {
+ ...
+ implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:0.30.0"
+}
+```
+```gradle:build.gradle
+kotlin {
+ experimental {
+ coroutines 'enable'
+ }
+}
+```
+```gradle:build.gradle
+repositories {
+ jcenter()
+}
+```
+#使い方
+Coroutineの作成には`Coroutineビルダー`を使用します。
+##runBlocking
+現在のスレッドをブロックするビルダーです。任意の型を返します。
+
+```kotlin
+runBlocking {
+ // 何かしらの処理
+}
+```
+###サンプル
+```kotlin
+fun main(args:Array<String>) {
+ println(1)
+ runBlocking {
+ println(2)
+ }
+ println(3)
+}
+
+/**
+ * 実行結果
+ * 1
+ * 2
+ * 3
+ */
+```
+##launch
+
+戻り値として`Job`を返すビルダーです。
+
+`0.26.1`から`launch`が`GlobalScope.launch`になりました。
+
+```kotlin
+GlobalScope.launch {
+ // 何かしらの処理
+}
+```
+###Sample
+現在のスレッドをブロックしないため、`launch`内の処理が実行されません。
+
+```kotlin
+fun main(args:Array<String>) {
+ println(1)
+ launch {
+ println(2)
+ }
+ println(3)
+}
+
+/**
+ * 実行結果
+ * 1
+ * 3
+ */
+```
+
+引数で実行するスレッドを指定できます。
+引数なしの場合は**Dispatchers.Default**が設定されます。
+
+`0.26.1`から`CommonPool`が`Dispatchers.Default`になりました。
+`0.26.1`から`UI`が`Dispatchers.Unconfined`になりました。
+
+```kotlin
+/**
+ * Dispatchers.Default -> バックグラウンドスレッド
+ * Dispatchers.Unconfined -> メインスレッド
+ */
+GlobalScope.launch(Dispatchers.Unconfined) {
+ // 何かしらの処理
+}
+```
+`Job#join()`を利用すれば、呼び出し先のcoroutineの終了まで呼び出し元のcoroutineを中断できます。
+
+```kotlin
+runBlocking {
+ GlobalScope.launch() {
+ // 何かしらの処理
+ }.join()
+}
+```
+###Sample
+
+```kotlin
+fun main(args:Array<String>) = runBlocking {
+ println(1)
+ GlobalScope.launch {
+ println(2)
+ }.join()
+ println(3)
+}
+
+/**
+ * 実行結果
+ * 1
+ * 2
+ * 3
+ */
+```
+##async
+戻り値として`Deffered<T>`を返すビルダーです。
+コルーチンの処理が終わったタイミングで戻り値を取得できます。
+
+`0.26.1`から`async`が`GlobalScope.async`になりました。
+
+```kotlin
+GlobalScope.async {
+ // 何かしらの処理
+}
+```
+###Sample
+`launch`同様、現在のスレッドをブロックしないため、`async`内の処理が実行されません。
+
+```kotlin
+fun main(args:Array<String>) {
+ println(1)
+ GlobalScope.async {
+ println(2)
+ }
+ println(3)
+}
+
+/**
+ * 実行結果
+ * 1
+ * 3
+ */
+```
+`Job#join()`同様、`Deffered<T>#await()`を利用すれば、呼び出し先のコルーチンの終了まで呼び出し元のコルーチンを中断できます。
+
+```kotlin
+runBlocking{
+ GlobalScope.async {
+ // 何かしらの処理
+ }.await()
+}
+```
+###Sample
+```kotlin
+fun main(args:Array<String>) = runBlocking {
+ println(1)
+ GlobalScope.async {
+ println(2)
+ }.await()
+ println(3)
+}
+
+/**
+ * 実行結果
+ * 1
+ * 2
+ * 3
+ */
+```
+#Suspending Function
+コルーチンを中断できる関数を`Suspending Function`と言います。
+`suspend`をつけることで宣言できます。
+コルーチン内か`Suspending Function`内からのみ実行できます。
+
+```kotlin
+suspend fun sampleSuspending(){
+ // 何かしらの処理
+}
+```
+###Sample
+`delay`は`Suspending Function`なので、実行できます。
+
+```kotlin
+fun main(args:Array<String>) = runBlocking {
+ println(1)
+ sampleSuspending()
+ println(3)
+}
+
+suspend fun sampleSuspending(){
+ delay(1000)
+ println(2)
+}
+
+/**
+ * 実行結果
+ * 1
+ * (1秒中断)
+ * 2
+ * 3
+ */
+```
+#まとめ
+非同期で依存関係がある場合コールバックが多くなりがちでしたが、簡潔に記述できるようになりました。
+
+#参考
+[Coroutines - Kotlin Programming Language]
+(https://kotlinlang.org/docs/reference/coroutines.html)
+[AndroidでKotlin Coroutinesを使ってみる]
+(http://tech.furyu.jp/blog/?p=6388)
+[eaglesakuraの技術ブログ]
+(https://eaglesakura.hatenablog.com/entry/2018/09/21/142152)
+[Kotlin の Coroutine を概観する]
+(https://qiita.com/kawmra/items/ee4acb7db61f70dec9a8)
+[入門Kotlin coroutines]
+(https://qiita.com/k-kagurazaka@github/items/8595ca60a5c8d31bbe37)