3
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

【Kotlin研修9日目】コルーチンを利用した非同期処理の実装

Posted at

コルーチンを利用した非同期処理

参考: AndroidでのKotlinコルーチン
参考: 図で理解するKotlinコルーチン

コルーチン

非同期処理が含まれるブロック{...}(=コルーチンスコープ)内で、非同期処理の実行中に、同期処理を中断できる仕組み(=デザインパターン)。

UIスレッドの処理によって呼び出された、ワーカースレッドでの処理を含む非同期処理のまとまり。

コルーチンを起動する、UIスレッドで動作する処理を処理A
処理Aによって呼び出されたワーカースレッドで動作する処理を処理B
処理Bによって呼び出されたUIスレッドで動作する処理を処理Cとすると、
処理C処理Bの終了を待つ必要があるため、同一処理ブロック{}でまとめて管理するのが望ましく、この処理のまとまりをコルーチンと呼ぶ。

また、処理B処理Cは互いに異なるスレッド上で動作するため、双方から見て非同期処理と言える。

コルーチンスコープ

コルーチン生存可能環境
コルーチンを管理しており、コルーチンの起動や実行中止を行う。

ViewModelでコルーチンを定義した場合はViewModelクラスのviewModelScopeプロパティ、
アクティビティでコルーチンを定義した場合はActivityクラスのlifecycleScopeプロパティがコルーチンスコープにあたる。


コルーチンを利用した非同期処理の実装

コルーチンを利用した非同期処理を実装する手順は、以下の通り。

  1. Gradle Scripts/build.gradle(Module)dependenciesブロックに、コルーチンの実装に必要な追加ライブラリを記述
  2. コルーチンの定義
  3. コルーチンスコープから2.で定義したコルーチンを起動

build.gradle(Module)への追加ライブラリの記述

コルーチンの実装に必要な機能は標準SDKで定義されていないため、追加ライブラリをGradle Scriptsフォルダのbuild.gradle(Module)ファイルに記述する必要がある。

また、ライブラリのバージョンは以下サイトを参考に、安定版の最新バージョン番号に書き換える。
Kotlinコルーチン
AndroidX Lifecycle

サンプルコード

build.gradle(Module)
...
dependencies {
    // Kotlinコルーチン
    implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.5.0"
    // AndroidX Lifecycle
    implementation "androidx.lifecycle:lifecycle-runtime-ktx:2.2.0"
    ...
}

コルーチンの定義

参考: CoroutineScope
非同期処理を行う処理を記述する際、
ワーカースレッドでの動作を保証する@WorkerThreadアノテーションの記述に加え、
呼び出し元スレッドでの処理を中断させながら、指定スレッドで処理を実行できるwithContext()メソッドを利用する。

なお、withContext()メソッドは内部的にsuspendキーワードが付与されているため、withContext()メソッドを利用する親メソッドにもsuspendキーワードを付与する必要がある。

定義

// スレッドを分離して処理を実行
// <- 内部的にsuspendキーワードが付与
suspend fun <T> withContext(
    context: CoroutineContext,
    block: suspend CoroutineScope.() -> T
): T
// パラメータ
// context: 分離先スレッド(Dispatchersクラス定数)
// block: スレッドを分離して実行する処理

Dispatchersクラス定数

クラス定数 内容
Dispatchers.Main UIスレッド
用途:
UI操作
Dispatchers.IO ワーカースレッド(I/Oスレッド)
用途:
Roomコンポーネント
ファイルの読み書き
ネットワークオペレーション
Dispatchers.Default ワーカースレッド(Defaultスレッド)
用途:
CPU負荷の高い作業

サンプルコード

MainActivity.kt
// 非同期(=ワーカースレッド)で実行する処理
// -> ワーカースレッドで動作することを明示的に記述(@WorkerThreadアノテーション)
// suspend: 実行中は元スレッド(=UIスレッド)の他の処理を中断させる
@WorkerThread
private suspend fun backgroundTaskRunner(): String {
    // ワーカースレッドで取得した値
    val returnVal = withContext(Dispatchers.IO) {
        ...  // ワーカースレッドで値を取得
    }
    // 取得した値を返却
    return returnVal
}

suspendシグネチャ

suspendシグネチャが付与されたメソッドの実行中に、メソッドの呼び出し元スレッドでの処理を中断させるキーワード。

コルーチンスコープによるコルーチンの起動

アクティビティコルーチンを定義した場合、アクティビティがもつlifecycleScopeプロパティを利用してコルーチンを起動する。

ViewModelでコルーチンを定義した場合、ViewModelクラスのviewModelScopeプロパティを利用してコルーチンを起動する。

定義

CoroutineScope.launch(
    context: CoroutineContext
    start: CoroutineStart
    block: suspend CoroutineScope.() -> Unit
)
// パラメータ
// context: コルーチンスコープへの追加コンテキスト
// -> 未指定の場合はDispatchers.Default(コルーチンスコープから継承)
// start: コルーチンの開始タイミング(CoroutineStartクラス定数)
// -> 未指定の場合はCoroutineStart.Default(即時実行)
// block: 起動するコルーチン

サンプルコード

MainActivity.kt
@UiThread
private fun asyncExecute() {

    // アクティビティのコルーチンスコープによるコルーチンの起動
    lifecycleScope.launch {

        // コルーチン
        // ワーカースレッドで動作する非同期処理
        backgroundTaskRunner()

        // UIスレッドで動作する非同期処理
        postBackgroundTaskRunner()
    }
}

コルーチンを利用した非同期処理の実装まとめ

// UIスレッドで動作する非同期処理を含む処理
@UiThread
private fun asyncExecute() {
    // ライフサイクルに最適化されたスコープを利用してコルーチンを起動
    lifecycleScope.launch {
        // 非同期(=ワーカースレッド)で行う処理
        backgroundTaskRunner()
        // 非同期処理後に同期(=UIスレッド)で行う処理
        postBackgroundTaskRunner()
    }
}

// ワーカースレッドで動作する処理(非同期処理)
@WorkerThread
private suspend fun backgroundTaskRunner() {
    withContext(Dispatchers.IO) {
        ...  // 非同期処理
    }
}

// 非同期処理後にUIスレッドで動作する処理(同期処理)
@UiThread
private fun postBackgroundTaskRunner() {
    ...  // 同期処理
}
3
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?