Summary : Coroutine + Flow 개념 정리 위한 문서
- 코틀린 동시성(비동기) 프로그래밍을 위한 API
- 코틀린이 비동기 코드로 작업하는 방식은 코루틴을 사용하는 것인데, 코루틴은 일시 중단 가능한 연산, 즉 함수가 어느 시점에 실행을 일시 중단하고 나중에 재개할 수 있다는 개념이다.
Coroutine의 장점
Kotlin
launch { ``` }
public fun CoroutineScope.launch(...):Job {...}
val job = CoroutineScope.launch(Dispatchers.Default) {
sleep(2000)
dosomething() // do suspend function
}
async { ``` }
public fun <T> CoroutineScope.async(...):Deferred<T> {...}
val defeered = CoroutineScope.async(Dispatchers.Default) {
sleep(2000)
dosomething() // do suspend function
}
CoroutineScope.launch(Dispatchers.Main) {
val dataOne = async(Dispatchers.IO) {
fetchSomeData1()
}
val dataTwo = async(Dispatchers.Default) {
fetchSomeData2()
}
showDialog(dataOne.await(), dataTwo.await())
}
runBlocking { ``` }
public fun <T> runBlocking(...): T { ... }
val result = runBlocking { sleep(2000)
dosometing() // do suspend function
}
withContext { ``` }
public fun <T> withContext(...): T { ... }
CoroutineScope.launch(Dispatchers.Main) {
val data = getDataFromServer()
withContext(Dispatcher.Main) {
showDialog(data) // do function UI Thread
}
}
CoroutineScope
public fun CoroutineScope(context: CoroutineContext): CoroutineScope =
ContextScope(if (context[Job] != null) context else context + Job())
CoroutineScope(Dispatchers.Main).launch {
dosometing()
}
GlobalScope
* Global scope is used to launch top-level coroutines which are operating on the whole application lifetime
* and are not cancelled prematurely.
public object GlobalScope : CoroutineScope{
/**
* Returns [EmptyCoroutineContext].
*/
override val coroutineContext: CoroutineContext
get() = EmptyCoroutineContext
}
GlobalScope(Dispatchers.Main).launch {
dosometing()
}
CoroutineNaming
Dispatchers
CoroutineScope(Dispatchers.Default).launch {
dosometing()
}
Job & Deferred
val job = Coroutine(Dispatcher.IO).launch {
doSomething()
}
job.start()
job.cancelAndJoin()
CoroutineScope.launch(Dispatchers.Main) {
val dataOne = async(Dispatchers.IO) {
fetchSomeData1()
}
val dataTwo = async(Dispatchers.Default) {
fetchSomeData2()
}
showDialog(dataOne.await(), dataTwo.await())
}
Coroutine Start Option
** //숫자 코드 실행 순서
// 1
CoroutineScope.launch(Dispatchers.IO) {
val deferred = async(start = CoroutineStart.LAZY) {
delay(1000)
dosometing()// 3
}
// 2
deferred.await()
// 4
}
** //숫자 코드 실행 순서
// 1
CoroutineScope.launch(Dispatchers.IO) {
val deferred = async(start = CoroutineStart.LAZY) {
delay(1000)
dosometing()// 4
}
// 2
deferred.start()
// 3
}
ExceptionHandling
public inline fun CoroutineExceptionHandler(crossinline handler: (CoroutineContext, Throwable) -> Unit): CoroutineExceptionHandler
/**
* CoroutineScope 내부 Exception 처리 Handler
*/
private val coroutineExceptionHandler = CoroutineExceptionHandler { context , throwable ->
Logger.w("$context ${throwable.message}")
if(ConstApp.isDevMode())
throwable.printStackTrace()
}
val job = launch {
try {
repeat(1000) { i ->
println("job: I'm sleeping $i ...") // 1
delay(500L)
}
} finally {
println("job: I'm running finally") // 3
}
}
delay(1300L) // delay a bit
println("main: I'm tired of waiting!") // 2
job.cancelAndJoin() // cancels the job and waits for its completion
println("main: Now I can quit.") // 4
val job = launch {
try {
repeat(1000) { i ->
println("job: I'm sleeping $i ...") // 1
delay(500L)
}
} finally {
withContext(NonCancellable) {
println("job: I'm running finally") //3
doSomesuspendFunction() // 4
println("job: And I've just delayed for 1 sec because I'm non-cancellable") // 5
}
}
}
delay(1300L) // delay a bit
println("main: I'm tired of waiting!") // 2
job.cancelAndJoin() // cancels the job and waits for its completion
println("main: Now I can quit.") // 6
withTimeout(1300L) {
repeat(1000) { i ->
println("I'm sleeping $i ...")
delay(500L)
}
}
[결과] : 1300 ms 이후 TimeoutCancellationException 발생
val result = withTimeoutOrNull(1300L) {
repeat(1000) { i ->
println("I'm sleeping $i ...")
delay(500L)
}
"Done" // will get cancelled before it produces this result
}
println("Result is $result")
[결과] : 1300 ms 이후 "Result is null" 출력
아래 포스트에서 계속 흐름...
https://velog.io/@devoks/Kotlin-Flow