[Android] kotlin으로 Coroutine사용하기

Coroutine을 이용하면 메모리를 효율적으로 사용하면서 손쉽게 비동기 처리를 할 수 있다.
Coroutine은 Thread가 아니다. 코드만 보면 동기적으로 동작하는 것 같지만 쓰레드 처럼 비동기적으로 동작하며 경량 쓰레드라고도 부른다.
하나의 쓰레드 안에서 여러개의 코루틴이 동시에 수행될 수 있다.
BackGround Task가 필요한 경우에 사용하는데 대표적인 예로,
1. 네트워크 리퀘스트 (Retrofit, Volley 등)
2. 내부저장소 접근 (Room, SQLite 등)
등이 있다.
1. Dependency 추가
안드로이드 스튜디오에서 코루틴을 사용하기 위해서는 build.gradle(:app)에 dependency를 추가해야한다.
dependencies {
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.9'
}
2. Coroutine 만들기
Coroutine은 다음과 같은 형식으로 만들 수 있다.
val scope = CoroutineScope(Dispatchers.IO)
scope.launch {
delay(1000)
println("peaceful coding")
}
- Dispatchers.IO를 이용하여 Coroutine이 실행 될 CoroutineScope를 만들고
- 만들어준 CoroutineScope에서 launch를 이용하여 { }안의 코드를 동작시킨다.
가장 기본적인 CoroutineScope의 사용방식이다.
Coroutine이 필요할 때마다 선언해주고, 필요없어지면 종료 시킬 수 있다.
먼저 Dispatcher.IO는 Coroutine Context이다.
실행 목적에 맞게 실행될 특정 Thread Pool을 지정해주는 것인데 대표적인 종류는 다음과 같다.
Dispatcher.Main : Main Thread에 대한 Context이며 UI 갱신이나, View작업에 사용.
Diapatcher.IO : 네트워킹이나 내부 DB접근 등 백그라운드에서 필요한 작업을 수행할 때 사용.
Dispatcher.Default : 크기가 큰 리스트를 다루거나 필터링을 수행하는 등 무거운 연산이 필요한 작업에 사용.
🌐 GlobalScope
GlobalScope.launch {
//Todo
}
CoroutineScope의 특별한 형태로 앱이 실행될 때부터 종료될때까지 Coroutine을 실행시킬 수 있다.
즉, Activity에서 GlobalScope를 통해 실행된 Coroutine은 Activity가 종료되어도 해당 Coroutine이 완료될 때까지 실행된다.
3. Coroutine Builder
Coroutine Builder는 Coroutine을 실행시켜주는 역할을 한다.
launch와 async가 있으며 { }안의 코드를 실행시켜주는 역할을 한다.
이 둘은 동일한 기능을 하지만 Job객체를 반환해주느냐, Deffered객체를 반환해 주느냐의 차이가 있다고 한다.
4. Suspend Function
Coroutine코드는 잠시 멈추거나(suspend) 다시 실행될 수 있기 때문에 코루틴 내에서 일반적인 method는 호출할 수가 없다.
때문에 Coroutine에서 실행될 수 있는 함수를 만드려면 함수를 정의할 때 suspend를 붙이면 된다.
suspend 함수는 안에서 또 다른 코루틴을 실행할 수 있다.
fun runCoroutine() {
GlobalScope.launch {
doSomething()
delay(1000)
println("peaceful coding")
}
}
suspend fun doSomething() {
GlobalScope.launch {
println("Have a nice day")
}
}
Activity와 동일한 LifeCycle을 갖는 Coroutine
class MainActivity : AppCompatActivity(), CoroutineScope {
private lateinit var job: Job
override val coroutineContext: CoroutineContext
get() = Dispatchers.Main + job
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
job = Job()
launch {
//Todo
}
override fun onDestroy() {
super.onDestroy()
job.cancel()
}
}
- CoroutineScope 인터페이스를 구현하고 Job객체를 선언한다.
- CoroutineScope인터페이스의 CoroutineContext를 오버라이드한다.
- Dispatcher.Main에 위에서 생성한 job을 더한다.
- Job객체를 생성하고 Activity가 종료될 때 수행중인 Job이 있다면 취소한다.