【Android】Kotlin コルーチン（coroutine）で非同期処理完了を待ち合わせして非同期結果を取得する

非同期処理で実行した結果を待ちわせしてMainスレッドで利用したいケースがあると思う。
コールバック（callback）を利用する等のいくつかの方法があるが、コルーチンの場合は簡単に実装できる。

まず最初に簡単にコルーチンで非同期で文字列を出力するだけの処理を実装してみる。（待ち合わせの処理はしない例）

```kotlin:CoroutineRepository.kt
class CoroutineRepository {

    // 非同期で3秒後にログを出力する
    fun execute() {
        Log.d("Coroutine", "execute start")
        var ayncString: String?
        GlobalScope.launch {
            withContext(Dispatchers.IO) {
                // 3秒スリープ（重たい処理）
                Thread.sleep(3000)
                ayncString = "123"
                Log.d("Coroutine", "ayncString:$ayncString")
            }
        }
        Log.d("Coroutine", "execute end")
    }
}
```

実行確認はActivityで行う。
実行確認用のActivityを用意する。

```kotlin:MainActivity.kt
class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        Log.d("Coroutine", "onCreate")
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        // ここで実行
        CoroutineRepository().execute()
    }

    override fun onStart() {
        Log.d("Coroutine", "onStart")
        super.onStart()
    }

    override fun onResume() {
        Log.d("Coroutine", "onResume")
        super.onResume()
    }
}
```

Activityを起動してみるとログに出力は↓のようになる。
```
onCreate
execute start
execute end
onStart
onResume
ayncString:123
```

非同期処理なので、Activityのライフサイクルは onResume まで進む。
3秒経過したら非同期処理のログが表示される。

コルーチンではなくThreadを使用しても同じように実装できる。

```kotlin:CoroutineRepository.kt
class CoroutineRepository {

    // Threadの例
    fun executeThread() {
        Log.d("Coroutine", "executeThread start")
        var ayncString: String?
        Thread {
            // 3秒スリープ（重たい処理）
            Thread.sleep(3000)
            ayncString = "123"
            Log.d("Coroutine", "ayncString:$ayncString")
        }.start()
        Log.d("Coroutine", "executeThread end")
    }
}
```

ここからが本番
非同期が完了した文字列を待ち合わせて取得したい。
**runBlocking** を利用すると簡単に実装可能である。

```kotlin:CoroutineRepository.kt
class CoroutineRepository {

    // 非同期内でセットした文字列を返す
    fun executeAwait(): String? {
        Log.d("Coroutine", "executeAwait start")
        var ayncString: String?
        runBlocking {
            withContext(Dispatchers.IO) {
                // 3秒スリープ（重たい処理）
                Thread.sleep(3000)
                ayncString = "123"
            }
        }
        return ayncString
    }
}
```

```kotlin:MainActivity.kt
class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        Log.d("Coroutine", "onCreate")
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        // 非同期処理を実行して文字列を出力
        val ayncString = CoroutineRepository().executeAwait()
        Log.d("Coroutine", "ayncString:$ayncString")
    }

    override fun onStart() {
        Log.d("Coroutine", "onStart")
        super.onStart()
    }

    override fun onResume() {
        Log.d("Coroutine", "onResume")
        super.onResume()
    }
}
```

実行してみるとログに出力は↓のようになる。
```
onCreate
executeAwait start
ayncString:123
onStart
onResume
```

待ち合わせをするので文字列を取得してからActivityのライフサイクルが進むことがわかる。（onCreateで3秒待ち合わせをすることになる）

メソッドを分割したい場合は↓のようにも実装することができる。
```kotlin:CoroutineRepository.kt
class CoroutineRepository {

    // 非同期内でセットした文字列を返す
    fun executeAwait(): String? {
        Log.d("Coroutine", "executeAwait start")
        var ayncString: String?
        runBlocking {
            ayncString = execute()
        }
        return ayncString
    }

    suspend fun execute(): String? {
        return withContext(Dispatchers.IO) {
            // 3秒スリープ（重たい処理）
            Thread.sleep(3000)
            "123"
        }
    }
}
```

コルーチンの非同期処理は簡単！