SharedFlow는 StateFlow의 일반화로 생각할 수 있다.
StateFlow는 기본적으로 새 구독자가 있을 때 마지막으로 알려진 값을 내보낸다. SharedFlow를 사용하면 내보낼 이전 값 수를 구성할 수 있다.
값의 버퍼가 가득 차면 어떤 일이 발생하는지 정의할 수 있다.
이는 LiveData가 쉽게 수행할 수 없는 고급 사용 사례에 대해 뛰어난 유연성을 제공한다.
먼저 관계를 보자면
Flow -> SharedFlow -> StateFlow로 상속 관계가 이루어진다.
버퍼 관련 설정을 할 수 있는데
extraBufferCapacity 로 버퍼 개수 설정이 가능하다.
버퍼를 설정하는 이유는 flow의 emit 이 빠르고 collect가 느리면 지정된 개수만큼 버퍼에 저장하는 식으로 실행하는데 이 개수를 넘어가면 onBufferOverflow 으로 설정한 버퍼 정책에 따라 동작하게 된다.
BufferOverflow.SUSPEND : buffer가 꽉 찼을 때 emit을 수행하면 emit 코드가 blocking 된다. 즉, buffer의 빈자리가 생겨야 emit 코드 이후의 코드가 수행될 수 있다.
BufferOverflow.DROP_OLDEST: buffer가 꽉 찼을 때 emit을 수행하면 오래된 데이터 부터 삭제하면서 새로운 데이터를 넣는다.
BufferOverflow.DROP_LATEST: buffer가 꽉찼을때 emit을 수행하면 최근 데이터를 삭제하고 새로운 데이터를 넣는다.
그러면 바로 예제를 보자.
class ViewModel : ViewModel() {
private val _dataState = MutableSharedFlow<DataState>(
replay = 0, extraBufferCapacity = 1, onBufferOverflow = BufferOverflow.DROP_OLDEST)
val dataState = _dataState.asSharedFlow()
fun getDataInfo() {
viewModelScope.launch {
_dataState.emit(DataState())
}
}
}
replay : 새로운 구독자들에게 이전 이벤트 방출 여부 (0 = 방출X, 1 = 방출)
extraBufferCapacity : 추가 버퍼 생성 여부 (1 = 생성)
OnBufferOverflow : 버퍼 초과시 처리 여부 (DROP_OLDEST = oldest 데이터 drop)
class Activity {
...
fun collectCardState() {
lifecycleScope.launchWhenStarted {
viewModel.dataState.collect { state ->
if (state.result != null) {
makeData(state.card)
}
if (state.error.isNotBlank()) {
showError(state.error)
}
}
}
}
}
SharedFlow와 똑같이 값을 받을 수 있습니다.