코루틴을 launch로 실행하면 함수가 차례대로 동기적으로 실행됩니다.
그러나 네트워크 작업과 같이 오래 걸리는 작업은 결과를 받기 전에 다른 작업을 실행하고 싶을 때가 있습니다.
이럴 때 우리는 비동기화로 실행을 하는데 코루틴에선 이를 async와 await를 사용하여 구현합니다.
[launch를 썼을 때]
package com.goodee.test
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import androidx.databinding.DataBindingUtil
import com.goodee.test.databinding.ActivityMainBinding
import kotlinx.coroutines.*
class MainActivity : AppCompatActivity() {
private val TAG: String = "로그"
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = DataBindingUtil.setContentView(this, R.layout.activity_main)
binding.nextBtn.setOnClickListener {
Log.d(TAG,"MainActivity - Before : run blocking ${Thread.currentThread().name}")
val startTime = System.currentTimeMillis()
CoroutineScope(Dispatchers.IO).launch {
// 네트워크 1 요청
val answer1 = networkCall1()
Log.d(TAG,"MainActivity - time : ${System.currentTimeMillis() - startTime} network1 is finish $answer1")
// 네트워크 2 요청
val answer2 = networkCall2()
Log.d(TAG,"MainActivity - time : ${System.currentTimeMillis() - startTime} network2 is finish $answer2")
}
}
}
// 3초의 응답 시간이 필요한 network 함수
private suspend fun networkCall1(): String {
delay(3000)
return "network1"
}
// 5초의 응답 시간이 필요한 network 함수
private suspend fun networkCall2(): String {
delay(5000)
return "network2"
}
}
[출력 결과]
2022-07-06 21:52:10.267 9962-9962/com.goodee.test D/로그: MainActivity - Before : run blocking main
2022-07-06 21:52:13.276 9962-9994/com.goodee.test D/로그: MainActivity - time : 3009 network1 is finish network1
2022-07-06 21:52:18.279 9962-9994/com.goodee.test D/로그: MainActivity - time : 8011 network2 is finish network2
network1의 요청이 끝나야 network2 요청을 하고 결과적으로 8(3 + 5)초의 시간이 걸린다.
동기적으로 실행 될 필요가 없는 이러한 함수들을 async(비동기)로 실행하면 앞선 네트워크 함수가 종료 되기 이전에 다음 함수를 실행하여 걸리는 시간의 총합을 아낄 수 있습니다.
async로 실행하여 리턴 받은 객체는 deferred이므로 await을 하여 결과를 기다려서 받을 수 있습니다.
package com.goodee.test
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import androidx.databinding.DataBindingUtil
import com.goodee.test.databinding.ActivityMainBinding
import kotlinx.coroutines.*
class MainActivity : AppCompatActivity() {
private val TAG: String = "로그"
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = DataBindingUtil.setContentView(this, R.layout.activity_main)
binding.nextBtn.setOnClickListener {
Log.d(TAG,"MainActivity - Before : run blocking ${Thread.currentThread().name}")
val startTime = System.currentTimeMillis()
CoroutineScope(Dispatchers.IO).launch {
// 네트워크 1 비동기 요청
val defer1 = async { networkCall1() }
// 네트워크 2 비동기 요청
val defer2 = async { networkCall2() }
val str1 = defer1.await()
Log.d(TAG,"MainActivity - time : ${System.currentTimeMillis() - startTime} network1 is finish $str1")
val str2 = defer2.await()
Log.d(TAG,"MainActivity - time : ${System.currentTimeMillis() - startTime} network2 is finish $str2")
}
}
}
// 2초의 응답 시간이 필요한 network 함수
private suspend fun networkCall1(): String {
delay(2000)
return "network1"
}
// 3초의 응답 시간이 필요한 network 함수
private suspend fun networkCall2(): String {
delay(3000)
return "network2"
}
}
[출력 결과]
2022-07-06 22:04:20.547 10616-10642/com.goodee.test D/로그: MainActivity - time : 2008 network1 is finish network1
2022-07-06 22:04:21.546 10616-10642/com.goodee.test D/로그: MainActivity - time : 3008 network2 is finish network2
'컴퓨터 언어 > Kotlin' 카테고리의 다른 글
코틀린 - const val vs val (0) | 2022.09.30 |
---|---|
06. 코루틴의 Job, waiting, Cancelation (0) | 2022.07.05 |
05. 코루틴의 runBlocking (0) | 2022.07.05 |
04. 코루틴의 Context (0) | 2022.07.05 |
03. 코루틴 suspend 함수 (0) | 2022.07.05 |