StateFlow vs SharedFlow

creativeBin·2022년 12월 26일
0

StateFlow(상태), SharedFlow(이벤트)

정리를 시작해보자. 😊

stateflow-and-sharedflow

1. StateFlow

기본 예시
val stateFlow = MutableStateFlow(0)

collet를 했을시에는

stateFlow.collect {
    println(it)
}

collect를 실행했을시에는 값을 얻을 수 있습니다.

최초 초기값을 0을 가져와서 emit하기 때문에 값은 0을 얻을 수 있습니다.

만약 이와 같이 값을 계속 설정하면

stateFlow.value = 1
stateFlow.value = 2
stateFlow.value = 2
stateFlow.value = 1
stateFlow.value = 3

이와 같은 결과를 얻게됩니다.

1
2
1
3

여기에서 '2'가 두번이 아니라 한번만 표시되는점에 유의해야합니다.
StateFlow는 연속적으로 반복되는 값을 보내지않기 때문입니다.

stateFlow.collect {
    println(it)
}

새 collect를 추가한다고 가정해봅니다.

그렇다면 우리는 3의 값을 얻을 수 있습니다.

결론
StateFlow는 마지막 값을 저장하고 새로운 Collect가 시작되면 새로운 값을 보냅니다.

2. SharedFlow

기본 예시
val sharedFlow = MutableSharedFlow<Int>()

위와 같이 SharedFlow를 선언합니다.

sharedFlow.collect {
    println(it)
}

Collect를 진행했을 시에 초기값을 갖지 않기때문에 값을 얻지 못합니다.

sharedFlow.emit(1)
sharedFlow.emit(2)
sharedFlow.emit(2)
sharedFlow.emit(1)
sharedFlow.emit(3)

위와 같이 값을 emit하게 되면

1
2
2
1
3

보시는바와 같이 우리는 2값을 두번 이상을 볼 수 있습니다. 즉 연속된 값을
보낸다는 것을 알 수 있습니다.

이제 새로운 컬렉터를 추가해본다고 가정해보겠습니다.

sharedFlow.collect {
    println(it)
}

SharedFlow는 마지막 값을 저장하지 않으므로 아무것도 얻지 못합니다.

이제 우리는 두개의 예를 보았습니다. 즉 정리해보자면

StateFlow는 SharedFlow의 한 유형입니다.

StateFlow는 SharedFlow의 전문화입니다.

StateFlow는 몇 가지 더 추가된 고정 재생 = 1인 SharedFlow입니다.


즉, 새로운 Collect를 실행할때마다, 즉시 현재 상태를 얻게 됩니다.

간단한 방법으로 설명해보자면

StateFlow = SharedFlow
            .withInitialValue(initialValue)
            .replay(count=1)
            .distinctUntilChanged()

실제로 아래와 같이 SharedFlow를 사용하여 StateFlow 동작을 얻을 수 있습니다.
val sharedFlow = MutableSharedFlow<Int>(
    replay = 1,
    onBufferOverflow = BufferOverflow.DROP_OLDEST
)
sharedFlow.emit(0) // initial value
val stateFlow = sharedFlow.distinctUntilChanged()

이것이 SharedFlow를 사용하여 StateFlow 동작을 얻는 방법입니다.

사용 사례에 따라 원하는 경우 replay = 2를 수행할 수 있는 것처럼 요구 사항에 따라 SharedFlow를 사용자 지정할 수 있습니다.

이제 Android 프로젝트에서 StateFlow 및 ShareFlow를 사용할 수 있는 위치를 알아볼 시간입니다.

사용 사례가 있다고 가정합니다. 네트워크에서 사용자 목록을 가져와서 UI에 표시합니다.

이제 Android 프로젝트에서 StateFlow 및 ShareFlow를 사용할 수 있는 위치를 알아볼 시간입니다.

사용 사례가 있다고 가정합니다. 네트워크에서 사용자 목록을 가져와서 UI에 표시합니다.

ViewModel에는 StateFlow가 있습니다.

val usersStateFlow = MutableStateFlow<Resource<List<User>>>(Resource.loading())
usersStateFlow.collect {

}

최초 Collect가 돌면서 값을 얻게 됩니다.

usersStateFlow: StateFlow가 초기 값을 가져와 즉시 내보낼 때 상태를 로드합니다.

이제 viewModel이 네트워크에서 데이터를 가져올 때입니다. 데이터를 usersStateFlow로 설정합니다.

usersStateFlow.value = Resource.success(usersFromNetwork)

사용자 데이터를 가져와서 UI에 표시합니다.

이제 방향이 변경 되면 ViewModel이 유지되고 Collect를 진행합니다.

usersStateFlow: 네트워크에서 설정한 사용자 목록입니다. (StateFlow는 마지막 값을 유지합니다).

😊 장점: 새로운 네트워크 호출이 필요하지 않습니다.

이제 StateFlow 대신 SharedFlow를 사용해 봅시다.

ViewModel에 SharedFlow가 있습니다.

val usersSharedFlow = MutableSharedFlow<Resource<List<User>>>()
usersSharedFlow.collect {

}

SharedFlow가 사용되므로 여기에서 collect를 통해 값을 얻을 수 없습니다.

이제 viewModel이 네트워크에서 데이터를 가져올 때입니다. 데이터를 usersSharedFlow로 설정합니다.

usersSharedFlow.emit(Resource.success(usersFromNetwork))

이제 방향이 변경 되면 ViewModel이 유지되고 활동에 있는 collect를 진행합니다.. 데이터를 저장하지 않는 SharedFlow가 사용되므로 여기에서 아무것도 수집되지 않습니다. 새로운 네트워크 호출을 해야 합니다.

👿 단점: 이미 데이터를 가지고 있었기 때문에 불필요한 네트워크 호출.

따라서 이 경우 SharedFlow 대신 StateFlow를 사용해야 합니다.

그러나 SharedFlow를 사용하여 StateFlow 동작을 가져오는 방법에 대해 위에서 본 것처럼 SharedFlow를 수정하여 데이터를 저장할 수 있습니다.

이제 StateFlow 대신 SharedFlow를 사용할 위치를 알아보기 위해 또 다른 예를 들어 보겠습니다.

작업을 수행하고 있다고 가정하고 작업이 실패하면 Snackbar를 표시해야 합니다.

ViewModel에 SharedFlow가 있습니다.

val showSnackbarSharedFlow = MutableSharedFlow<Boolean>()
showSnackbarSharedFlow.collect {

}

SharedFlow가 사용되므로 여기에서 아무것도 수집되지 않습니다.

그런 다음 viewModel이 작업을 시작하고 실패할 때. showSnackbarSharedFlow에 true 값을 설정합니다.

showSnackbarSharedFlow.emit(true)

collect했을시에 값은 true로 가져오고 Snackbar를 표시합니다.

이제 방향이 변경 되면 ViewModel이 유지되고 활동에 있는 collect가 진행되어지면서. SharedFlow는 마지막 값을 유지하지 않으므로 여기에서 아무것도 수집되지 않습니다. 괜찮습니다. 방향 변경 시 Snackbar를 다시 표시하지 않아야 합니다.

장점: Snackbar가 의도한 대로 다시 표시되지 않습니다.

이제 SharedFlow 대신 StateFlow를 사용해 보겠습니다.

ViewModel에는 StateFlow가 있습니다.

val showSnackbarStateFlow = MutableStateFlow(false)
showSnackbarStateFlow.collect {

}

이제 활동을 열자마자 활동이 수집을 구독합니다. 다음이 수집됩니다.

showSnackbarStateFlow: StateFlow가 초기 값을 가져와서 즉시 내보내므로 false입니다.

이제 viewModel이 작업을 시작하고 실패할 때. showSnackbarSharedFlow에 true 값을 설정합니다.

showSnackbarStateFlow.value = true

활동 수집기는 값을 true로 가져오고 Snackbar를 표시합니다.

이제 방향이 변경 되면 ViewModel이 유지되고 활동에 있는 수집기가 수집을 다시 구독합니다. 다음이 수집됩니다.

showSnackbarStateFlow: true는 StateFlow가 마지막 값을 유지하므로 여기에서 수집됩니다. Snackbar가 다시 표시됩니다. 그리고 그것은 좋지 않습니다. 방향 변경 시 Snackbar를 다시 표시하지 않아야 합니다.

👿 단점: 필요하지 않은 Snackbar가 다시 표시됩니다.

따라서 이 경우 StateFlow 대신 SharedFlow를 사용해야 합니다.

이제 StateFlow와 SharedFlow를 잘 이해했으므로 어떤 경우에 사용할 것인지 쉽게 결정할 수 있습니다.

이것은 Kotlin의 StateFlow 및 SharedFlow에 관한 것입니다.

profile
언제나 항상 즐겁게 New vibes 😎

0개의 댓글