Open2

Android Coroutines 入門

darmaT0o0darmaT0o0

参考
https://developer.android.com/kotlin/coroutines/coroutines-adv?hl=ja

Kotlin コルーチンを使用すると、アプリの応答性を保ちながら、ネットワーク呼び出しやディスク オペレーションなどの長時間実行タスクの管理を行うための非同期コードを、クリーンかつシンプルに記述できます。

build.gradle(app)
dependencies {
    implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.9")
}

コルーチンを実行すべき場所を指定するために、Kotlin では、デベロッパーが使用できる次の 3 つのディスパッチャを用意しています。
Dispatchers.Main - このディスパッチャを使用すると、コルーチンはメインの Android スレッドで実行されます。UI を操作して処理を手早く作業する場合にのみ使用します。たとえば、suspend 関数の呼び出し、Android UI フレームワーク オペレーションの実行、LiveData オブジェクトのアップデートを行う場合などです。
Dispatchers.IO - このディスパッチャは、メインスレッドの外部でディスクまたはネットワークの I/O を実行する場合に適しています。たとえば、Room コンポーネントの使用、ファイルの読み書き、ネットワーク オペレーションの実行などです。
Dispatchers.Default - このディスパッチャは、メインスレッドの外部で CPU 負荷の高い作業を実行する場合に適しています。ユースケースの例としては、リストの並べ替えや JSON の解析などがあります。

コルーチンを作成する

suspend fun  fetchTwoDocs() = 
   coroutineScope{
         val func1 = async { fetchDoc() }
         val func2 = async { fetchDoc() }
        func1.await()
        func2.await()

        //OR

        val deferreds = listOf(
             async { fetchDoc() }
             async { fetchDoc() }
        )
        deferreds.awaitAll()
   }

suspend fun fetchDoc(){
        
}

CoroutineScope
CoroutineScope は、launch または async を使用して作成したコルーチンをすべて追跡します。実行中の作業(実行中のコルーチン)は、いつでも scope.cancel() を呼び出してキャンセルできます。Android では、一部の KTX ライブラリが特定のライフサイクル クラスに独自の CoroutineScope を提供しています。たとえば、ViewModel には viewModelScope、Lifecycle には lifecycleScope があります。ただし、ディスパッチャとは異なり、CoroutineScope ではコルーチンは実行されません。

// runBlocking
fun main() = runBlocking(Dispatchers.Default) {
    launch { // launch a new coroutine and continue
        delay(1000L) // non-blocking delay for 1 second (default time unit is ms)
        println("World!") // print after delay
    }
    println("Hello") 
}

// suspendの追加
fun main() = runBlocking(Dispatchers.Default) { // this: CoroutineScope
    launch { doWorld() }
    println("Hello")
}

// this is your first suspending function
suspend fun doWorld() {
    delay(1000L)
    println("World!")
}
darmaT0o0darmaT0o0

CoroutineContextについて

  • Job: コルーチンのライフサイクルを制御する

https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-job/

  • Coroutine job: Jobの生成と処理をする。(launch,async,GlobalScope)...GlobalScopeは親のコルーチン野江教を受けないので独自のCoroutineContext を持つことができる。
  • CompletableJob: Jobが完了したかどうかを親コルーチン、子コルーチンに知らせる。

Jobは、親がキャンセルされると、子もキャンセルするよ。CancellationException以外でエラーが発生する処理をSupervisorJobで制御できるよ。

Jobの状態遷移

  • New
  • Active
  • Completing
  • Completed
  • Cancelling
  • Cancelled
                                          wait children
    +-----+ start  +--------+ complete   +-------------+  finish  +-----------+
    | New | -----> | Active | ---------> | Completing  | -------> | Completed |
    +-----+        +--------+            +-------------+          +-----------+
                     |  cancel / fail       |
                     |     +----------------+
                     |     |
                     V     V
                 +------------+                           finish  +-----------+
                 | Cancelling | --------------------------------> | Cancelled |
                 +------------+                                   +-----------+


  • CoroutineDispatcher: 適切なスレッドに処理を送信する

https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-coroutine-dispatcher/

  • Default
  • IO
  • Unconfined
  • Main
  • CoroutineName: コルーチンに名前をつけれる。デバッグに使える

https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-coroutine-name/

  • CoroutineExceptionHandler: キャッチされない例外を処理します

https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-coroutine-exception-handler/

withContextを使って見る

コルーチンを実行すべき場所を指定するために、Kotlin では、デベロッパーが使用できる次の 3 つのディスパッチャを用意しています。

  • Dispatchers.Main - このディスパッチャを使用すると、コルーチンはメインの Android スレッドで実行されます。UI を操作して処理を手早く作業する場合にのみ使用します。たとえば、suspend 関数の呼び出し、Android UI フレームワーク オペレーションの実行、LiveData オブジェクトのアップデートを行う場合などです。

  • Dispatchers.IO - このディスパッチャは、メインスレッドの外部でディスクまたはネットワークの I/O を実行する場合に適しています。たとえば、Room コンポーネントの使用、ファイルの読み書き、ネットワーク オペレーションの実行などです。

  • Dispatchers.Default - このディスパッチャは、メインスレッドの外部で CPU 負荷の高い作業を実行する場合に適しています。ユースケースの例としては、リストの並べ替えや JSON の解析などがあります。

  • withContext

     suspend fun <T> withContext(
           context: CoroutineContext,
           block: suspend CoroutineScope.() -> T
     ): T