Android/Coroutine

안드로이드 코루틴 flow의 StateFlow 와 SharedFlow

최데브 2022. 3. 5. 20:44

둘다 비슷하게 쓰인다. 마치 LiveData 와 비슷한 점이 많은데

분명 써보면 차이점은 있다. 

난 이 차이점에 대해서 명확하게 설명하지 못했던 사람이고 

이 글은 그걸 설명해보려고 적는 글이다.

 

둘다 데이터 스트림에서 hot 흐름을 가지는데

hot흐름 cold 흐름에 대해서는 코루틴은 아니지만 Rx 를 다루면서 말했었으니 아래 링크를 참고하길 바란다.

https://choi-dev.tistory.com/138

 

RxJava - Hot Observable , Cold Observable

이전에 쓴 글(아래 링크 참고) 에서 뒷쪽에 https://choi-dev.tistory.com/107?category=972011 RxJava - Observable을 제외한 다른 생산자들 전 포스팅에서는 Observable에 대해서 알아봤다. 기본적인 생산자였는..

choi-dev.tistory.com

 

먼저 StateFlow 를 알아보자.

 

StateFlow는 현재 상태와 새로운 상태 업데이트를 수집기에 내보내는 관찰 가능한 상태 홀더 흐름이다.

value 속성을 통해서도 현재 상태 값을 읽을 수 있다. 상태를 업데이트하고 흐름에 전송하려면 MutableStateFlow 클래스의 value 속성에 값을 할당 해야한다. StateFlow는 관찰 가능한 변경 가능 상태를 유지해야 하는 클래스에 아주 적합하다.

    // Backing property to avoid state updates from other classes
    private val _uiState = MutableStateFlow(LatestNewsUiState.Success(emptyList()))
    // The UI collects from this StateFlow to get its state updates
    val uiState: StateFlow<LatestNewsUiState> = _uiState

안드로이드 공식문서에 있는 코드다. 위 처럼 쓸 수 있는데 LiveData와는 다른점이 눈에 보인다.

StateFlow는 초기값을 설정해야줘야 한다는 점이다.

그리고 또 LiveData와 다른 점은 view가 Stop 상태가 되면 livedata는 라이프사이클을 알고 있어서 자동으로 소비자가 등록취소되지만 StateFlow는 알아서 취소하지 않기 때문에 호출할때 Lifecycle.repeatOnLifecycle 로 사용해야 라이프사이클에 대응을 할 수 있다.

 

+2022.07.19 추가  StateFlow 는 내부적으로 중복제거를 시행하기 때문에 똑같은 값이 연속으로 emit 되면 뒤에 들어온 값은 생략해버린다. 그래서 이벤트 처리에 사용하기엔 부적합하다.

 

다음은 SharedFlow 를 알아보자.

StateFlow와 비슷해보이지만 눈에 띄는 다른점은 초기값 설정이 없어도 되는 점

StateFlow 와 다르게 중복제거를 시행하지 않아서 event처리에 용이하다.

그리고 replay 라는 옵션을 사용해서 이전에 내보낸 값을 새 구독자를 위해 다시 보낼 수 있다는 점(stateflow는 해당옵션이 1로 고정되어있다고 생각하면 된다. 그래서 이전의 값을 새 구독자를 위해 보내지 못한다.)과

버퍼 관련 설정을 할 수 있는데

extraBufferCapacity 로 버퍼 개수 설정이 가능하다.

버퍼를 설정하는 이유는 flow의 emit 이 빠르고 collect가 느리면 지정된 개수만큼 버퍼에 저장하는 식으로 실행하는데 이 개수를 넘어가면  onBufferOverflow 으로 설정한 버퍼 정책에 따라 동작하게 된다.

onBufferOverflow 의 정책은 아래와 같다.

 

BufferOverflow.SUSPEND : buffer가 꽉 찼을 때 emit을 수행하면 emit 코드가 blocking 된다. 즉, buffer의 빈자리가 생겨야 emit 코드 이후의 코드가 수행될 수 있다.

BufferOverflow.DROP_OLDEST: buffer가 꽉 찼을 때 emit을 수행하면 오래된 데이터 부터 삭제하면서 새로운 데이터를 넣는다.

BufferOverflow.DROP_LATEST: buffer가 꽉찼을때 emit을 수행하면 최근 데이터를 삭제하고 새로운 데이터를 넣는다.

 

 

 

 

 

 

 

 

 

반응형