非同期処理で実行した結果を待ちわせしてMainスレッドで利用したいケースがあると思う。
コールバック(callback)を利用する等のいくつかの方法があるが、コルーチンの場合は簡単に実装できる。
まず最初に簡単にコルーチンで非同期で文字列を出力するだけの処理を実装してみる。(待ち合わせの処理はしない例)
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を用意する。
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を使用しても同じように実装できる。
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 を利用すると簡単に実装可能である。
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
}
}
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秒待ち合わせをすることになる)
メソッドを分割したい場合は↓のようにも実装することができる。
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"
}
}
}
コルーチンの非同期処理は簡単!