Flow 만들어보기(feat. Flow builder)
·
Study/Kotlin
이번 글에서는 Flow builder를 사용해 Flow를 만들어본다. flowOf 사용하기첫번째는 flowOf라는 함수를 사용해 Flow를 생성해보겠다. val flow1 = flowOf()val flow2 = flowOf(1, 2, 3)흔히 MutableList를 만드는 방식과 매우 유사하다. 어떤 값을 넣지 않으면 제네릭으로 타입을 명시해주어야 하고,값을 넣게 된다면 타입을 명시하지 않아도 컴파일러가 자동으로 감지한다. asFlow 사용하기두번째로는 asFlow라는 함수를 사용하는 방법이다. listOf("a", "b", "c").asFlow()asFlow 함수는 Iterable, Sequence 등의 확장 함수로 선언되어 있다. flow 람다 사용하기마지막으로는 flow 람다를 사용하는 방법이다..
Flow 개념 살펴보기
·
Study/Kotlin
이번 예시는 팩토리얼 계산 함수를 사용할 예정이다. 일반적 함수 구현fun main() { val result = calculateFactorial(5) println("result: $result")}private fun calculateFactorial(num: Int): BigInteger { var factorial = BigInteger.ONE for (i in 1 .. num) { Thread.sleep(10) factorial = factorial.multiply(BigInteger.valueOf(i.toLong())) } return factorial}이렇게 작성된 함수에서는 계산 결과만 받을 수 있다. 그렇다면 계산 과정은 어떻게 ..
예외 처리에서 Lifecycle 고려하기
·
Study/Kotlin
이전 글에서 짧게 viewModelScope에서의 예외 처리 예시를 살펴보았다. 이번에는 이전 글을 바탕으로 발생할 수 있는 Lifecycle 관련 예외 처리 시나리오를 세워 본다. 문제가 될만한 상황 검토하기viewModelScope.launch { supervisorScope { val deferred = async { throw RuntimeException() } val result = try { deferred.await() } catch (e: Exception) { println(e) } // Some Ui updates(Vulnerable point) }}이 코드에서 가장 위험한 부분은 result 변수 이후에 viewModelSco..
viewModelScope 예외 처리 예시
·
Study/Kotlin
이전 글에서 coroutineScope와 supervisorScope 함수로 예외 처리하는 방법을 살펴보았다. 이제는 실전인 viewModelScope에서 어떻게 예외 처리를 하면 좋을까에 관한 내용이다. 문제 상황 살펴보기viewModelScope.launch { val deferred = async { throw RuntimeException() } val result = try { deferred.await() } catch (e: Exception) { println(e) }}이런 예시가 있다고 해보자. 내가 처음 예측했던 결과는 정상적으로 catch 문에서 예외를 잡을 수 있을 것이라 생각했다. 하지만, 결과는 앱 크래시로 이어졌다. 문제 상황 ..
supervisorScope 함수를 사용한 예외 처리
·
Study/Kotlin
이번에는 저번 글의 coroutineScope 함수와 달리 supervisorScope를 사용해보는 시간이다. 바로 예제 코드부터 보자. supervisorScope를 사용한 예외 처리 시도하기fun main() = runBlocking { try { supervisorScope { launch { throw RuntimeException() } } } catch(e: Exception) { println("Caught: $e") }}먼저 저번 글에서 coroutineScope를 supervisorScope로 대치해보았다. 실행 결과를 예측해보자. launch 내부에서 발생한 예외는 처리되지 않고 앱 크래시가 발생할 것이다. 왜..
coroutineScope 함수를 사용한 예외 처리
·
Study/Kotlin
이번 글에서는 coroutineScope라는 함수를 사용해서 예외를 처리해보도록 하겠다. 대소문자를 잘 구별해야한다. 대문자로 시작하는 CoroutineScope 함수와는 사뭇 다르다. 예외 발생 상황 보기fun main() = runBlocking { launch { throw RuntimeException() }}나는 위와 같은 코드를 실행해서 예외를 발생시킬 것이다. 당연히 launch에서 발생한 예외는 try-catch나 CoroutineExceptionHandler가 없기에비정상 종료로 이어질 것이다. try-catch로 처리해볼까?fun main() = runBlocking { try { launch { throw RuntimeException() } ..
launch vs async in Coroutines Exception Handling
·
Study/Kotlin
이번 글에서는 코루틴에서 예외를 처리할 때 launch와 async 코루틴 빌더의 차이를 살펴보려고 한다. launch 사용 예제val scope = CoroutineScope(Job())scope.launch { delay(100) throw RuntimeException()}Thread.sleep(300)이 코드를 실행하면 어떤 결과가 나올까?예외를 처리하는 부분은 없다.콘솔 창에서 볼 수 있듯 예외가 전파되어 종료되었다. async 사용 예제val scope = CoroutineScope(Job())scope.async { delay(100) throw RuntimeException()}Thread.sleep(300)이번에는 단순히 launch를 async로 바꿔보았다. 실행 결과는 과연..
Coroutines try-catch vs ExceptionHandler
·
Study/Kotlin
이번 글에서는 try-catch와 ExceptionHandler를 비교해보려고 한다. 얼핏 보기에는 둘 다 예외 처리의 기법으로만 보고 넘어갈 수도 있지만,각각 사용해야하는 상황이 다르기 때문이다. try-catch 관점try-catch는 예외가 발생하고나서도 계속 작업이 필요한 경우에 사용된다. 예를 들면, 코루틴 내부에서 재시도하는 로직이 필요한 경우이다. try-catch 구문을 사용해 예외를 잡아내고 해당 예외를 다시 전파시키지 않는다면예외는 상위 계층으로 전파되지 않는다.(부모 코루틴에게 전파되지 않는다) 예외가 발생했음에도 상위 계층으로 예외가 전파되지 않는다면Structured Concurrency를 해칠 수 있다. ExceptionHandler 관점try-catch와는 달리 계속해서 작업이..
Exception Handling Using ExceptionHandler in Coroutines
·
Study/Kotlin
이번에는 CoroutineExceptionHandler로 예외 처리를 해보도록 하자. 기존 try-catch 구문과는 어떤 차이가 있는지도 볼 예정이다. 처리할 코드val scope = CoroutineScope(Job())scope.launch { throw RuntimeException()}Thread.sleep(1000) CoroutineExceptionHandler 사용 지점이 핸들러는 Coroutine의 Context 요소이다. 이전 글에서의 기억을 떠올려본다면 가장 대표적인 Context 요소는 Dispatcher일 것이다. 또한, '+' 연산자를 사용하면 여러 Context 요소를 사용할 수 있다. 그럼 위 코드에서 어떤 위치에 핸들러를 주입해야할까? 정답은 두 위치에서 가능한데, 하나는 J..
Exception Handling Using try-catch Clause in Coroutines
·
Study/Kotlin
이번 글은 코루틴에서 try-catch절을 사용해 예외 처리를 해보는 시간이 될 것이다. 일반적인 예외 처리 상기하기fun main() { generateException()}fun generateException() { throw RuntimeException()}이런 예외를 try-catch절로 처리한 상황과 그렇지 않은 상황을 떠올려보자. 먼저 예외 처리를 해두었다면 프로그램이 정상적으로 실행이 종료된다. 그렇지 않은 경우 로그를 남기며 프로그램에 크래시가 발생한다. 코루틴에 적용해보기fun main() { val scope = CoroutineScope(Job()) scope.launch { generateException() } Thread.sleep(100)}fu..