이번 글에서는 LifecycleScope를 소개해본다. 다만 제목 그대로 간단히 알아보려 하는데 이전 글에서 알아본 ViewModelScope와 비슷하기 때문이다. LifecycleScope의 lifecycle 알아보기생명주기는 생각보다 심플하다. Lifecycle owner가 살아있는 동안 해당 스코프도 살아있게 된다. 상황에 따라 Activity, Fragment 등이 될 수 있다. 해당 owner가 destroy될 때 LifecycleScope에서 실행된 모든 코루틴은 cancel된다. 가장 대표적인 destroy 상황은 화면 회전에 의한 Activity destroy이다. 이렇게 되면 특정 작업을 수행하다가도 cancel되어버리는 상황이 발생하기에이런 경우, ViewModelScope를 사용하는..
이번에는 드디어 이전 예제들에서 사용해왔던 viewModelScope에 대해 알아보도록 하자. ViewModelScope LifecycleviewModelScope는 ViewModel의 lifecycle과 연관되어 있다. 다르게 말하면 viewModelScope에서 시작된 코루틴은 ViewModel이 살아있는 경우 계속 실행된다. 당연히 ViewModel onCleared 메소드가 호출되는 시점에viewModelScope에서 시작된 코루틴은 모두 cancel된다. ViewModelScope 구현 살펴보기이 스코프는 ViewModel이 clear될 때 자동으로 cancel된다는위의 lifecycle 설명에서 말했던 부분이 보인다. Dispatcher 확인하기MainCoroutineDispatcher.imm..
GlobalScope에 대해 설명하기 전 가장 저명한 사실을 하나 얘기하고 시작한다. 우리는 앱에서 GlobalScope를 사용할 일이 거의 없을 것이다. 공식문서에서도 되도록 사용하지 않는 것을 권장하는 뉘앙스를 풍긴다. 사용하지 않을 이유 찾기 제한된 수명 주기가 없다.이 뜻을 앱 관점에서 보면 GlobalScope 안에서 시작된 코루틴은앱 프로세스가 종료될 때까지 종료되지 않는다는 것이다. 어떠한 Job에도 엮이지 않는다.제목 그대로를 코드로 확인해보자.println("GlobalScope Job: ${GlobalScope.coroutineContext[Job]}")이 코드를 실행시켜보자.GlobalScope Job: null위와 같은 결과가 나온다. 위 결과로 유추할 수 있는 것이 또 하나가 생겼..
이번 글에서는 구조적 동시성(Structured Concurrency)의 특징을 정리해본다. 1. 모든 코루틴은 제한된 수명이 있는 위치에서 시작되어야 한다.가장 대표적인 예로 Activity가 될 수 있다. RxJava에서는 특정 시점에서 disposable을 모아 처리해야 하는데컴파일러는 개발자가 처리하는 코드를 작성하지 않아도 경고하지 않는다. 이렇게 clear 혹은 cancel의 과정이 없다면OOM(Out Of Memory) 에러 혹은 앱 크래시가 발생할 수 있을 것이다. 반면에 코루틴을 사용할 때 예시로 사용했던 코드를 보면 viewModelScope가 있다. 이 스코프는 ViewModel 수명에 엮여있다. 따라서 ViewModel이 수명에 따라 clear될 때,viewModelScope에서 실..
이번 글에서는 전에 다루었던 withContext로 스레드를 전환 후 연산 작업을 더 빠르게 수행해보려고 한다. 기존에는 팩토리얼 계산을 Default Dispatcher를 사용해 하나의 코루틴에서 연산을 수행했다.이번에는 여러 개의 코루틴에서 연산을 수행한다. 어떤 구조로 실행할까팩토리얼을 몇개의 코루틴으로 나눠 실행할지 정해야 한다.실행할 코루틴 갯수만큼 연산할 숫자의 길이를 동등하게 분배한다.작은 범위를 계산하는 서브 코루틴을 동시에 실행시킨다.모든 서브 코루틴이 종료되는 것을 기다린다.모든 서브 코루틴이 종료되면 fold 함수를 사용해 작은 범위들을 모두 곱한다. 코드suspend fun calculateFactorial( factorialOf: Int, numberOfC..
이번 글은 최근 Java -> Kotlin 변환과Java 클래스에서 Kotlin 클래스를 사용하면서 겪은 이슈를 공유해본다. 문제 상황 설명먼저 Java 클래스를 Kotlin 클래스로 변경했다. 이 때 특정 변수는 자료형을 변경하면서까지 리팩토링을 진행했다. 그리고 다시 변경한 Kotlin 클래스를 Java 클래스에서 사용하는 부분이 필요했다.(아래처럼 말이다)class SomeData { var a: UInt = 0 var b: Int = 0}public class User { public void someMethod() { SomeData someData = new SomeData(); someData.getB(); someData.getA(); }} Kot..
CoroutineScope(이하 Scope)는 CoroutineContext(이하 Context)라는 하나의 프로퍼티를 가지고 있다. 더불어 모든 Coroutine은 특정 Scope에서 실행된다. 그리고 여러 개의 Coroutine은 같은 Scope에서 실행될 수 있다. 특정 Coroutine과 그 자식 Coroutine을같은 Scope에서 실행하게 되면 Job 객체들이 부모-자식 계층을 구성하게 된다. 이렇게 형성된 부모-자식 계층은 구조적 동시성에서 중요한 부분이다. 같은 Scope에서 실행된 Coroutine은기본적으로 해당 Scope의 Context를 상속받는다. 하지만 각 Coroutine은 다른 Context로 실행될 수 있고,이것도 계층 구조를 따라 특정 Coroutine이 A라는 Conte..
저번 글에서 예고했던 대로 메인 스레드에서 했던 무거운 작업을 이제 다른 스레드에서 작업시켜보자.(이전 글 확인하기) 이전 동작 이해하기아까 첨부한 링크에서의 이전 글을 보면우리는 viewModelScope를 사용해 CPU 연산이 무거운 작업을 메인 스레드에서 실행했다. 그렇게 수초간 메인 스레드가 blocking되었고, 다른 UI는 반응할 수 없었다. 그리고 우리가 실행했던 viewModelScope의 Context를 확인하는 방법이 하나 있다.fun performCalculationOnMain(factorial: Int) { viewModelScope.launch { println("Coroutine Context: $coroutineContext") var result = BigInt..
이번 글은 저번 CoroutineContext와 CoroutineScope를 소개한 것에 이어서 Dispatcher에 대해 알아보겠다. Dispatcher의 역할Dispatcher는 해당 코루틴이 어느 스레드나 스레드 풀에서 실행될지 결정한다. Dispatcher의 종류Dispatcher는 이미 정의된 몇가지가 있는데 이에 대해 짧막하게 알아보자. Dispatchers.MainMain Dispatcher는 오직 UI가 있는 애플리케이션에서만 사용할 수 있다. 안드로이드의 경우, UI 작업을 오직 메인 스레드에서만 허용하므로Main Dispatcher를 사용해 메인 스레드에서 실행할 수 있다. 해당 Dispatcher가 Main Looper와 연결된 Handler를 사용하기 때문이다. 우리가 Main Di..
이번에는 CoroutineContext는 대체 무엇인지 알아보자. 그리고 간단히 CoroutineScope 구조까지 살펴보도록 하겠다. viewModelScope로 찾아보기viewModelScope는 CoroutineScope라는 인터페이스를 상속받아 만들어진 녀석이다. 그리고 CoroutineScope 인터페이스를 확인해보자.보다시피 CoroutineContext를 가지고 있는 걸 볼 수 있다. 그리고 다시 한 번 CoroutineContext가 무엇인지 들어가보자.문서 최상단을 읽어보면 CoroutineContext는 여러 Context Element를 포함하고 있다는 사실을 알 수 있다. 여기서 가장 중요한 Element에는 바로 Dispatcher, Job, ExceptionHandler, Nam..