Coroutines
A coroutine is a concurrency design pattern that you can use on Android to simplify code that excutes asynchronously.
On Android, coroutines help to manage long-running tasks that might otherwise block the main thread and cause your app to become unresponsive.
Coroutines are a Kotlin feature that converts async callbacks for long-runnign tasks, such as database or network access, into sequential code.
Use suspend functions to make async code sequential.
https://kotlinlang.org/docs/coroutines-overview.html#tutorials
- Basic
- Coroutine builder
- launch : 비동기적으로 코루틴을 시작한다는 것을 의미하며, 결과값을 반환하지 않는 Job 객체를 리턴한다.
- runBlocking : 현재 스레드를 블로킹하면서 코루틴을 실행하고, 코루틴의 결과를 반환한다.
- Scope
- CoroutineScope : 코루틴의 실행 범위를 지정하고, 코루틴의 생명 주기를 관리한다.
- GlobalScope : 프로그램 전체에서 사용할 수 있는 전역 코루틴 스코프로 사용되며, 앱 전체의 생명주기에 종속된다.
- Suspend function
- suspend : 해당 함수가 코루틴 또는 다른 suspend 함수 내에서만 호출될 수 있음을 나타낸다.
- delay() : 지정된 시간 동안 코루틴을 일시 중지한다.
- join() : 시작된 코루틴이 완료될 때까지 현재 코루틴을 일시 중지한다.
- Structured concurrency
- 코루틴은 정의된 스코프 내에서 실행되며, 스코프가 종료되면 모든 코루틴이 정상적으로 종료되도록 구조화된 동시성을 제공한다.
- Coroutine builder
- Cancellation and Timeouts
- Job
- cancel() : 실행중인 코루틴을 취소시 사용, 이 메서드는 코루틴을 즉시 종료하지 않는다.
* "즉시 종료하지 않는다"
->cancel() 함수를 호출하면 해당 코루틴의 작업 취소가 요청되지만, 코루틴이 그 즉시 중단되거나 종료되는 것은 아니다. 코루틴은 협조적 취소(Cooperative cancellation)를 따르기 때문에 코루틴 내부에서 취소 가능 지점을 주기적으로 확인하거나, 취소 상태를 직접 확인해야 한다. - Cancellation is cooperative
- way 1: to periodically invoke a suspending (call suspend)
- way 2: explicitly check the cancellation status(isActive)
- Timeout
- withTimeout : 지정된 시간이 지나면 TimeoutCancellationException을 던져 코루틴을 취소한다.
- withTimeoutOrNull : 지정된 시간이 지나면 'null' 을 반환하고 코루틴을 취소하지만 예외는 던지지 않는다.
- etc
- yield() : 다른 코루틴에 실행을 양보하고 현재 코루틴이 다음 차례가 올 때 까지 중지한다.
- withContext(NonCancellable) - in rare case
: 특정 경우에 코루틴이 취소되지 않도록 보장하며, 일반적으로 취소할 수 없는 작업을 완료해야 할 때 사용된다.
- cancel() : 실행중인 코루틴을 취소시 사용, 이 메서드는 코루틴을 즉시 종료하지 않는다.
- Job
* 코루틴취소 관련 - Suspension Points : 'suspend' 함수를 호출하는 지점에서만 취소가 가능, 코루틴 내부에서 긴 계산 작업이나 블록 작업을 수행할 경우엔 주기적으로 'yield()'함수를 호출하거나, 'isActive'속성을 체크하는 것이 좋다. 이런 방법을 통해 코루틴이 취소 요청을 적절히 확인하고 반응할 수 있다. - 리소스 정리 : 코루틴이 취소되었을 경우, 열려 있는 파일이나 네트워크 연결 같은 자원을 정리하는 것이 좋다. 이를 위해 'try/finally' 블록을 사용하여 코루틴이 취소되더라도 필수적인 정리 작업이 수행되도록 할 수 있다. - NonCancellable : withContext(NonCancellable)는 코루틴이 중간에 취소되어서는 안 되는 중요한 정리 작업을 수행할 경우 유용하다. 예를 들어, 거래를 완료하거나 중요 데이터를 저장하는 동안에는 이 컨텍스트를 사용하여 코루틴의 취소를 방지할 수 있다. - Timeout 처리 : 'withTimeout' 함수를 사용하면 지정된 시간 안에 작업이 완료되지 않을 경우 'TimeoutCancellationException'을 발생시켜 코루틴을 취소할 수 있다. 작업이 정상적으로 완료되거나 중요한 상황에서 예외 처리를 통해 특정 로직을 실행할 수 있다. |
- Composing suspending functions
: https://kotlinlang.org/docs/composing-suspending-functions.html
- Sequential by default
- To simplify code that executes asynchronously.
- Converts async callbacks to sequential code.
- Use suspend functions to make async code sequential
- Sequential by default
val time = measureTimeMillis {
val one = doSomethingUsefulOne()
val two = doSomethingUsefulTwo()
println("The answer is ${one + two}")
}
println("Completed in $time ms")
suspend fun doSomethingUsefulOne(): Int {
delay(1000L) // pretend we are doing something useful here
return 13
}
suspend fun doSomethingUsefulTwo(): Int {
delay(1000L) // pretend we are doing something useful here, too
return 29
}
코루틴을 사용하여 비동기적이지만 순차적인 작업을 수행하는 방법에 대한 예시.
각 함수는 독립적으로 실행되지만, 결과는 순차적으로 계산되며, 메인 스레드의 차단 없이 전체 프로세스가 관리된다. 이는 코루틴이 비동기 작업을 간결하고 효율적으로 처리할 수 있게 해준다
- Concurrent using async
- What if there are no dependencies between invocations
- we want to get the answer faster, by doing both concurrently?
- This is twice as fast, because the two coroutines execute concurrently.
- Note that concurrency with coroutines is always explicit.
val time = measureTimeMillis {
val one = async { doSomethingUsefulOne() }
val two = async { doSomethingUsefulTwo() }
println("The answer is ${one.await() + two.await()}")
}
println("Completed in $time ms")
'async'를 사용하면 코루틴이 시작되며, 경량 스레드처럼 동작하면서 다른 코루틴과 동시에 실행된다. 'async'는 결과 값을 가질 수 있는 'Deferred'객체를 반환한다. 이 'Deferred'객체를 통해 나중에 결과를 얻을 수 있으며 '.await()' 메소드를 사용해 해당 결과를 비동기적으로 기다릴 수 있다. 이 방법을 사용하면 여러 비동기 작업을 병렬로 처리하고 결과를 쉽게 합칠 수 있어 전체 실행 시간을 단축시킨다. 'async'는 또한 'job'의 한 형태로써, 필요에 따라 작업을 취소할 수 있다.
* Deferred ?
: Coroutine에서 'async'빌더를 사용할 때 반환되는 특수한 타입. 'Job'의 서브클래스로, 비동기 작업의 결과를 나중에 받을 수 있게 해준다. 'Deferred'는 비동기 작업이 완료될 때까지 결과를 기다리는데 사용할 수 있는 '.await()'메서드를 제공한다.
- await() 메서드를 통해 비동기 작업의 결과를 요청하고 기다릴 수 있다.
- 작업을 기다리는 동안 다른 작업을 차단하지 않는다, 메인 스레드나 다른 중요한 작업을 방해하지 않고 결과를 기다릴 수 있다.
- cancel()로 취소할 수 있다.
- 비동기 작업 중 발생한 예외는 await() 호출 시점에 처리, await()는 작업 중 발생한 예외를 그대로 던지므로, 호출자는 이를 적절히 처리해야 한다.
- Lazily started async
- Optionally, async can be made lazy by setting its start parameter
- its result is required by await, or if its job's start function is invoked
- if we just call await in println without first calling start
val time = measureTimeMillis {
val one = async(start = CoroutineStart.LAZY) { doSomethingUsefulOne() }
val two = async(start = CoroutineStart.LAZY) { doSomethingUsefulTwo() }
// some computation
one.start() // start the first one
two.start() // start the second one
println("The answer is ${one.await() + two.await()}")
}
println("Completed in $time ms")
'Software Development > Application Develop' 카테고리의 다른 글
Jetpack Compose - Navigation (0) | 2024.07.27 |
---|---|
Android Zetpack Compose 기초 (0) | 2024.07.27 |
Android Sensor (0) | 2022.10.28 |
How to create walking step counter App using Accelerometer sensor and Shared Preference in Android? (0) | 2022.10.28 |
Flutter HelloWorld Sample Code로 flutter 기초 개념 이해하기 (0) | 2021.09.02 |