Kotlin coroutines on Android | Android Developers
안드로이드 코루틴 공식문서를 참고하고 정리한 포스팅 입니다.
코루틴은 실행을 일시 중단
하고 재개
할 수 있는 비동기 프로그래밍을 위한 라이브러리. 서브루틴을 사용하여 어떤 작업을 하기 위해 함수가 호출이 되고 함수의 동작이 끝나면 자신을 호출했던 메인루틴으로 돌아옴.
suspend
키워드를 사용하여 코루틴간 일시 중단 - 재개를 수행하며 실행된다.일시 중단 함수
를 사용하여 비동기식 코드를 동기식으로 구현이 가능하다.구글 권장 아키텍처 가이드에 맞춰 코루틴을 사용하는 예제를 살펴보자.
시나리오는 다음과 같다.
<aside> 📖 네트워크 요청을 보내고, 결과를 기본 스레드로 반환한다.
</aside>
UI 스레드에서 네트워크 요청을 할 경우에 응답을 받을 때까지 스레드가 대기하거나 차단된다. 스레드가 차단되는 경우엔 OS는 UI 작업을 하지 못하며, 앱이 정지되고 ANR이 표시될 수 있다.
// 네트워크 요청을 응답을 모델링하기 위한 Result 클래스
sealed class Result<out R> {
data class Success<out T>(val data: T) : Result<T>()
data class Error(val exception: Exception) : Result<Nothing>()
}
class LoginRepository(private val responseParser: LoginResponseParser) {
private const val loginUrl = "<https://example.com/login>"
// 동기식이며, 호출 스레드를 차단한다.
fun makeLoginRequest(
jsonBody: String
): Result<LoginResponse> {
val url = URL(loginUrl)
(url.openConnection() as? HttpURLConnection)?.run {
requestMethod = "POST"
setRequestProperty("Content-Type", "application/json; utf-8")
setRequestProperty("Accept", "application/json")
doOutput = true
outputStream.write(jsonBody.toByteArray())
return Result.Success(responseParser.parse(inputStream))
}
return Result.Error(Exception("Cannot open HttpURLConnection"))
}
}
위 코드에서 makeLoginRequest
함수를 실행하면 비동기식이 아니기 때문에 호출한 스레드를 차단한다. 이는 네트워크 요청이므로, 메인 스레드에선 실행하면 안된다. 안전을 위해 코루틴을 사용해서 코드를 변경해보자.
class LoginRepository(...) {
...
suspend fun makeLoginRequest(
jsonBody: String
): Result<LoginResponse> {
return withContext(Dispatchers.IO) {
// Blocking network request code
}
}
}
makeLoginRequest
를 일시중단 함수로 설정해줬다. 코루틴에서 해당 함수를 호출한 경우 코루틴은 이 함수가 재개될 때 까지 일시정지되고, 다른 코루틴을 실행한다.
makeLoginRequest
함수는 viewModelScope.launch
에서 사용된다. 이는 설정을 안해줬을 경우 디폴트는 Dispatcher.Main
이므로 코루틴 스코프를 설정해주거나, withContext
를 사용하여 알맞은 스코프로 변환해줘야 한다.
위 예제에선 withContext
를 사용하여 코루틴 컨텍스트를 변경해줌으로 네트워크 작업에 용이하다. withContext
의 작업이 끝나면, 요청 결과와 함께 기본 스레드에서 실행을 재개한다.