해당 게시물은 과거에 작성한 블로그 내용을 옮겨 온 것으로, 가독성이 떨어지고 내용이 부정확할 수 있습니다.
- Coroutine은 경량 스레드로 비유 가능
- 스레드는 아니지만 비동기적인 프로그래밍이 가능
- 비동기적으로 실행되는 코드를 간소화하기 위하여 사용 가능한 동시 실행 설계 패턴
- 서로 협력하는 함수로, 여러 함수가 번갈아 가며 실행
- 사용 전 dependencies에 코루틴 추가 필요
dependencies {
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.9")
}
- 경량: suspend 기능을 지원하여 단일 스레드에서 많은 코루틴 실행 가능
- 메모리 누수 감소: 구조화 된 동시 실행을 사용해 범위 내에서 작업 실행
- 취소 지원: 실행 중인 코루틴의 계층 구조를 통하여 자동으로 캔슬 가능
- Jetpack 동합: 대다수의 Jetpack 라이브러리에 코루틴을 완전히 지원하는 확장 프로그램 포함
- launch와 async 명령어를 통해 코루틴 실행
- launch: 반환 값이 없는 명령어
- launch 블록 안에 다시 launch를 써서 다른 코루틴 실행 가능
- async: Deferred < T > 객체 반환
- Deferred< T > 클래스: await() 메소드를 제공하여 작업 완료까지 대기 후 T 타입 객체를 반환
GlobalScope.launch{
launch{
Log.d(TAG, "Launch")
}
val value: Int = async{
1 + 3
}.await()
Log.d(TAG, "Async - value: $value")
}
- Global.launch: launch로 코루틴 실행
- async{…}: async로 코루틴 실행
- 1 + 3의 결과를 value에 삽입
- .await: async의 코루틴 종료 시까지 대기 후 value return
- suspend function: 코루틴의 실행을 잠시 정지 후 resume
- 함수 생성 시 suspend를 적으면 사용 가능
private suspend fun example(){
GlobalScope.launch{
sleep(1000)
Log.d(TAG, "suspend")
}
- withContext(): 코루틴 실행을 다른 스레드로 이동
- async와 동일한 기능
- await()을 호출하지 않아도 된다는 차이점이 존재
class LoginRepository(...) {
...
suspend fun makeLoginRequest(
jsonBody: String
): Result<LoginResponse> {
// 코루틴 실행을 IO 디스패처로 이동
// 해당 코루틴을 I/O 작업용으로 예약된 스레드에서 실행해야 함을 나타냄
return withContext(Dispatchers.IO) {
// Blocking network request code
}
}
}
- Dispathcers.Main: 안드로이드 내의 메인 스레드
- UI와 상호작용 및 빠른 작업 실행 가능
- Dispatchers.IO: 기본 스레드 외부에서 디스크 또는 네트워크 I/O를 실행하도록 최적화된 디스패처
- 파일 읽기, AAC의 Room 등
- Dispatchers.Default: CPU를 많이 사용하는 작업을 기본 스레드 외부에서 실행하도록 최적화 된 디스패처
- 목록을 정렬하거나 JSON 파싱 등
- Scope: 코루틴이 동작하는 범위
- GlobalScope: 어플리케이션 종료 시까지 코루틴 실행 가능
- 액티비티가 종료되어도 코루틴 작업이 끝날 때까지 코루틴이 동작
- CoroutineScope: launch 또는 async를 사용하여 만든 코루틴을 추적
- 동작 중인 코루틴을 scope.cancle()로 취소 가능
- 안드로이드의 특정 KTX 라이브러리 중에는 특정 생명 주기 클래스에 viewModelScope나 lifecycleScope 등 자체 CoroutineScope를 제공
- 일련의 요소를 사용해 코루틴의 동작 정의
- Job: 코루틴의 생명 주기 제어
- CoroutineDispatcher: 적절한 스레드로 작업을 전달
- CoroutineName: 디버깅에 유용한 코루틴의 이름
- CoroutineExceptionHandle: 예외 처리
- 웹 어플리케이션, HTTP 서비스, 모바일 및 브라우저 어플리케이션 등의 연결된 앱을 쉽게 구축 가능한 프레임워크
- KTOR를 사용하여 코틀린으로 비동기 클라이언트 및 서버 어플리케이션 작성을 가능하게 하는 코틀린 프레임워크
- KTOR 사용 시 앱 수준의 gradle에 의존성 추가 필요
- 필요한 의존성만 추가하는 것을 권장
dependencies{
implementation "io.ktor:ktor-client-cio:1.6.3"
implementation "io.ktor:ktor-client-core:1.6.3"
implementation "io.ktor:ktor-client-android:1.6.3"
implementation "io.ktor:ktor-client-serialization:1.6.3"
implementation "io.ktor:ktor-client-logging:1.6.3"
implementation "io.ktor:ktor-client-gson:1.6.3"
}
- gradle에 의존성 추가
- request를 보내고 response를 받을 data class 정의
- HTTP 통신을 위한 클래스 추가
- 클래스 내에 HttpClient 객체 추가
class HttpRequestHelper {
// CIO: HttpClientEngineFactory로, Coroutine based I/O
private val client: HttpClient = HttpClient(CIO)
}
- 매니페스트에 INTERNET permission 추가
<uses-permission android:name="android.permission.INTERNET" />
- Http request 진행
- get(): 클라이언트에 get() 호출 시 바로 통신 결과 가져올 수 있음
withContext(Dispatchers.IO){
val url = "https://cat-fact.herokuapp.com/facts/random"
val response: HttpResponse = client.get(url)
}
- call.parameters[“paramName”]: 인덱스 접근자 함수
- call.receive: 제네릭 변수를 사용해 request body를 코틀린 객체로 역직렬화
- call.respond(): 코틀린 객체를 가져와서 해당 객체의 지정 형식으로 직렬화해서 http 응답 반환
- call.respondText(): 텍스트를 응답으로 보낼 시의 respond를 구현한 함수
- 문자열 응답 반환