티스토리 뷰
cancen() & cancelAndJoin()
Coroutine에서 취소가 어떻게 진행되는지 확인해봅니다.
// cancel과 cancelAndJoin의 차이
public suspend fun Job.cancelAndJoin() {
cancel()
return join()
}
cancel()을 실행했을 때 취소되지 않고 Coroutine이 계속 실행됩니다. 즉 Coroutine 내부에서 진행될 때 취소를 확인하여 종료할 수 있도록 설계 해야합니다. (개발자가 직접 취소 지점을 정할 수 있습니다.)
val job = CoroutineScope(Dispatchers.IO).launch {
for (i in 0 until 5) {
Log.d("PASS", "Running")
Thread.sleep(1000L)
}
}
lifecycleScope.launch {
delay(1000L)
job.cancel()
}
2022-01-08 00:15:14.054 19334-19367/com.taetae98.coroutine D/PASS: Running
2022-01-08 00:15:15.055 19334-19367/com.taetae98.coroutine D/PASS: Running
2022-01-08 00:15:16.057 19334-19367/com.taetae98.coroutine D/PASS: Running
2022-01-08 00:15:17.060 19334-19367/com.taetae98.coroutine D/PASS: Running
2022-01-08 00:15:18.063 19334-19367/com.taetae98.coroutine D/PASS: Running
val job = CoroutineScope(Dispatchers.IO).launch {
for (i in 0 until 5) {
Log.d("PASS", "Running")
Thread.sleep(1000L)
yield()
}
}
lifecycleScope.launch {
delay(1000L)
job.cancel()
}
val job = CoroutineScope(Dispatchers.IO).launch {
for (i in 0 until 5) {
if (isActive) {
Log.d("PASS", "Running")
Thread.sleep(1000L)
}
}
}
lifecycleScope.launch {
delay(1000L)
job.cancel()
}
2022-01-08 00:36:11.718 19690-19721/com.taetae98.coroutine D/PASS: Running
2022-01-08 00:36:12.721 19690-19721/com.taetae98.coroutine D/PASS: Running
위와 같이 2가지 방법으로 코딩했을 경우 정상적으로 종료된 것을 확인할 수 있다. 즉 개발자가 직접 yield(), isActive 등으로 비활성 상태에서 종료 지점을 정할 수 있습니다.
val job = CoroutineScope(Dispatchers.IO).launch {
try {
for (i in 0 until 5) {
Log.d("PASS", "Running")
yield()
delay(1000L)
}
} catch (e: CancellationException) {
Log.d("PASS", "ERROR : $e")
}
}
lifecycleScope.launch {
delay(1000L)
job.cancel()
}
2022-01-08 00:44:19.600 20187-20221/com.taetae98.coroutine D/PASS: Running
2022-01-08 00:44:20.613 20187-20223/com.taetae98.coroutine D/PASS: ERROR : kotlinx.coroutines.JobCancellationException: StandaloneCoroutine was cancelled; job=StandaloneCoroutine{Cancelling}@43635db
실제로 Coroutine이 종료된 시점에서 yield(), delay() 등을 호출하면 CancellationException이 발생하는 것을 확인할 수 있습니다.
NonCancellable
이미 취소된 함수에서 어떠한 작업을 위해 suspend 함수를 호출해야 할 경우 보통의 상황에선 CancellationException이 발생할 것 입니다. withContext(NonCancellable)을 통해서 정지된 Coroutine에서 suspend 함수를 호출할 수 있습니다.
val job = CoroutineScope(Dispatchers.IO).launch {
try {
for (i in 0 until 5) {
Log.d("PASS", "Running")
yield()
delay(1000L)
}
} catch (e: CancellationException) {
Log.d("PASS", "ERROR : $e")
} finally {
withContext(NonCancellable) {
delay(1000L)
Log.d("PASS", "coroutine is finished!!")
}
}
}
lifecycleScope.launch {
delay(1000L)
job.cancel()
}
2022-01-08 00:58:58.531 20284-20319/com.taetae98.coroutine D/PASS: Running
2022-01-08 00:58:59.551 20284-20321/com.taetae98.coroutine D/PASS: ERROR : kotlinx.coroutines.JobCancellationException: StandaloneCoroutine was cancelled; job=StandaloneCoroutine{Cancelling}@43635db
2022-01-08 00:59:00.562 20284-20321/com.taetae98.coroutine D/PASS: coroutine is finished!!
withTimeout
withTimeout을 사용하여 지정된 시간에만 작동되는 Coroutine을 만들 수 있습니다. withTimeout을 통해 Exception이 발생한 경우 TimeoutCancellationException이 발생하고 CancellationException을 상속 받습니다.
public class TimeoutCancellationException internal constructor(
message: String,
@JvmField internal val coroutine: Job?
) : CancellationException(message), CopyableThrowable<TimeoutCancellationException> {
val job = CoroutineScope(Dispatchers.IO).launch {
withTimeout(2000L) {
try {
for (i in 0 until 5) {
Log.d("PASS", "Coroutine is running")
delay(1000L)
}
} catch (e: TimeoutCancellationException) {
Log.e("PASS", "Exception : $e")
}
}
}
2022-01-08 01:03:34.056 20418-20453/com.taetae98.coroutine D/PASS: Coroutine is running
2022-01-08 01:03:35.068 20418-20453/com.taetae98.coroutine D/PASS: Coroutine is running
2022-01-08 01:03:36.058 20418-20453/com.taetae98.coroutine E/PASS: Exception : kotlinx.coroutines.TimeoutCancellationException: Timed out waiting for 2000 ms
'Android > Coroutine' 카테고리의 다른 글
Android Coroutine - Exception (0) | 2022.01.16 |
---|---|
Android Coroutine - Job Lifecycle (0) | 2022.01.15 |
Android Coroutine - Coroutine Builder (0) | 2022.01.07 |
Android Coroutine - CoroutineContext (0) | 2022.01.07 |
Android Coroutine - Scope (0) | 2022.01.07 |
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
- Total
- Today
- Yesterday
링크
TAG
- rxjava
- clean code
- TDD
- 클린코드
- viewmodel
- Android
- Exception
- ViewModelStoreOwner
- observable
- isActive
- gradle
- 보이스카우트 규칙
- Coroutine
- DART
- git
- 클린 코드
- CancellationException
- ConcatAdapter.Config
- Widget
- Flutter
- null
- 연산자
- DSL
- ViewModelProvider
- 코루틴
- Kotlin
- commit
- 함수
- ConcatAdapter
- Flowable
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 | 31 |
글 보관함