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로 바꿔보았다. 실행 결과는 과연..
Android Studio error loading build artifacts 해결
·
Dev experience/Android
이번에는 정말 기이한 현상을 만났다. 제목에서 일부 내용이 보일텐데 빌드 시작조차 되지 않는 현상이었다. 문제 발생 이전 상황기존 groovy를 사용하던 build.gradle을 모두 kts로 변환하고,toml을 사용해 version catalog를 도입했다. 그리고 테스트를 위해 여러번 빌드를 수행했고 실제로 앱이 실행되는 것을 확인했다. 이후, Android Stuido Narwhal Feature Drop 2025.1.2 버전으로 안드로이드 스튜디오를 업데이트하고아래와 같은 현상이 발생되기 시작했다. Gradle sync 이후 빌드 시 에러 발생Error loading build artifacts from: ~/build/intermediates/apk_ide_redirect_file/debug/c..
Coroutines try-catch vs ExceptionHandler
·
Study/Kotlin
이번 글에서는 try-catch와 ExceptionHandler를 비교해보려고 한다. 얼핏 보기에는 둘 다 예외 처리의 기법으로만 보고 넘어갈 수도 있지만,각각 사용해야하는 상황이 다르기 때문이다. try-catch 관점try-catch는 예외가 발생하고나서도 계속 작업이 필요한 경우에 사용된다. 예를 들면, 코루틴 내부에서 재시도하는 로직이 필요한 경우이다. try-catch 구문을 사용해 예외를 잡아내고 해당 예외를 다시 전파시키지 않는다면예외는 상위 계층으로 전파되지 않는다.(부모 코루틴에게 전파되지 않는다) 예외가 발생했음에도 상위 계층으로 예외가 전파되지 않는다면Structured Concurrency를 해칠 수 있다. ExceptionHandler 관점try-catch와는 달리 계속해서 작업이..
Full Screen Intent 권한 관련 업데이트 거부
·
Dev experience/Android
이번에는 Full Screen Intent 권한 선언에 관련하여 업데이트를 거부당하고 문제를 해결한 내역을 공유해보고자 한다. 대체 어떻게 선언을 한걸까먼저 앱에 대한 간단한 소개를 하자면, 일단 웹뷰를 보여주는게 거의 모든 기능이었다. 여기서 브릿지 함수 등은 웹뷰 동작이라고 제외하게 되면 실제 네이티브에서 사용하는 기능은 통화 기능이었다. 따라서 내가 선택했던 권한 선언은 아래 이미지와 같다. 심사를 제출해보자이제 위에서 본 선언을 토대로 심사를 제출해보았다. 글 제목에서 예상하다시피 당연히 결과는 업데이트 거부였다.이런 메일을 받고 나는.. 내 앱에 통화 기능이 있다니깐?!이라는 억울한 심정이 있었고.. 저희 앱에는 통화 기능이 있는데 권한 선언이 잘못된 점이 없다고생각한다는 내용을 담아 이의 신청..