카테고리 없음

[Android] kotlin으로 Coroutine사용하기

핸드피쓰 2021. 2. 6. 16:14

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") 
}
  1. Dispatchers.IO를 이용하여 Coroutine이 실행 될 CoroutineScope를 만들고
  2. 만들어준 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()  
     }
}
  1. CoroutineScope 인터페이스를 구현하고 Job객체를 선언한다.
  2. CoroutineScope인터페이스의 CoroutineContext를 오버라이드한다.
  3. Dispatcher.Main에 위에서 생성한 job을 더한다.
  4. Job객체를 생성하고 Activity가 종료될 때 수행중인 Job이 있다면 취소한다.