비동기적으로 작업을 처리하는 코루틴에서 suspend 함수를 사용하면 작업이 모두 완료 된 후에 단일값만을 반환 받을 수 있다.
하지만, 중간 중간 진행 되는 코루틴 작업 중에 갱신 되는 값까지 반환받을 수 있다면 로직 업데이트를 더 촘촘히 수행할 수 있을 것이다.
Flow는 이런 요구를 충족하기 위해서 만들어진 타입이다.
Flow는 빌더를 통해서 생성하는데 Suspend 키워드를 따로 붙여주지 않아도 블록 내부의 작업이 코루틴에서 수행 된다.
Flow에서 값을 방출하는 데에는 Emit을 사용하고, 값을 회수하는 데에는 Collect 함수를 사용한다.
Flow는 Collect로 값을 요청하지 않는 한 값을 방출하지 않는데, 이것을 Cold Stream이라고 한다.
반대로, Hot Stream은 요청이 있건 없건 값을 계속 방출하는 형식이다.
Repository 레벨에서는 Flow를 사용하고, UI와 레포지토리를 엮는 ViewModel단에서는 LiveData를 사용하기를 추천한다고 한다.
- LiveData
- 생명주기를 가진 데이터 홀더로 UI와 연결하면 자동으로 화면을 업데이트 할 수 있다는 이점
- 메인 스레드에서 동작하므로 워커 스레드에서 작업을 처리해야 되는 데이터 레이어에서는 사용하기가 적절치 않다.
- 안드로이드와 밀접하게 연결되어 있어 테스트가 까다로워진다.
- Flow
- CoroutineScope 안에서 동작하므로 필요에 따라 적당한 쓰레드를 골라서 사용할 수 있다.
- 안드로이드 라이프사이클 감지 가능
- 안드로이드 의존성 제거 가능
- Cold Stream이므로 Collect가 되어야만 값을 방출한다.
- 상태가 없으므로 현재 값을 얻을 수 없다는 한계가 있다.
Hot Stream으로 동작하게 구성된 Flow의 한 종류이다.
SharedFlow에서 상태를 부여해서 현재 값을 얻을 수 있게 제안을 가한 것이 StateFlow이다.
LiveData와 비슷한 동작을 하면서도 UI에서 데이터 레벨까지 사용할 수 있는 데이터 홀더이다.
구글은 UI를 표시하는 데이터 홀더를 LiveData에서 StateFlow로 변경하고 있는 추세이다.
fun <T> Flow<T>.stateIn(scope: CoroutineScope, started: SharingStarted, initialValue: T): StateFlow<T>