코틀린 & Java

LiveData와 StateFlow의 차이

코딩하는후운 2021. 12. 27. 17:22
반응형

LiveData에는 Post 및 Set의 2가지 방출 기능이 있습니다.
기사 중 하나에 따르면 LiveData의 단점은 두 가지 값 방출 기능, 즉 setValue 및 postValue가 있다는 것입니다.
setValue — 메인 스레드에서만 사용할 수 있습니다. 그렇지 않으면 충돌합니다.
postValue — 모든 스레드에서 사용할 수 있습니다. 그러나 메인 스레드가 사용 중이면 값이 떨어지고(잃어버린) 가장 최근에 게시된 값만 사용됩니다.

 

StateFlow에는 1개의 방출 기능만 있습니다.
세트도 포스트도 없습니다. 설정할 stateFlow.value일 뿐입니다. 따라서 배경인지 전경인지(메인 스레드) 걱정할 필요가 없습니다.

 

  • 주 스레드가 사용 중일 때 stateFlow가 어떻게 동작하는지 궁금합니다. postValue를 사용할 때 liveData와 동일한가요? (아래에 또 다른 질문이 있습니다)
  • postValue를 사용할 때 liveData의 경우 값이 삭제되면 방출에서 삭제됨을 의미합니까, 아니면 캐시조차 되지 않습니까?

두 가지 질문에 답하기 위해 4가지 다른 시나리오를 실험으로 설정했습니다. 

이러한 모든 시나리오는 기본 스레드가 사용 중인 경우에만 의미가 있습니다.


그래서 내 모든 실험에서,
나는 1에서 10까지를 방출하는 루프를 가지고 있습니다. 

그 사이의 delay(1000)은
저는 Thread.sleep(3000)을 사용하여 데이터를 내보내려고 시도한 후 메인 스레드를 바쁘게 만듭니다.

 

1. StateFlow

fun triggerStateFlow() {
    viewModelScope.launch(Dispatchers.Default) {
        repeat(10) {
            delay(1000)
            ++_stateFlow.value
        }
    }
    Thread.sleep(3000)
}

사용 중인 MainThread를 기다리는 처음 3초 동안에는 방출된 데이터가 표시되지 않습니다.
그러나 StateFlow에 캐시됩니다. 

그러나 MainThread가 해제되면 마지막 캐시된 값이 그에 따라 3에서 10까지 표시되는 위치에서 시작됩니다.
요컨대, 값은 표시되지는 않지만 방출되고 캐시됩니다. 방출된 값은 전혀 손실되지 않지만 표시되지 않을 뿐입니다.

 

2. LiveData with PostValue

fun triggerLivePostData() {
    viewModelScope.launch(Dispatchers.Default) {
        repeat(10) {
            delay(1000)
            _liveDataPost.postValue(_liveDataPost.value + 1)
        }
    }
    Thread.sleep(3000)
}

사용 중인 MainThread를 기다리는 처음 3초 동안 방출된 데이터는 캐시되거나 표시되지 않습니다.
그러나 MainThread가 해제되면 처음 2개의 방출 값이 손실되기 때문에 그에 따라 1에서 8까지 표시되는 값을 캐싱하기 시작했습니다.
간단히 말해서 값은 내보내지지만 기본 스레드가 사용 중일 때 캐시되거나 표시되지 않습니다. 

방출된 값이 손실됩니다.

 

3. LiveData with SetValue using WithContext

여기서는 LiveData의 setValue를 사용합니다. 

MainThread에 있어야 하므로 withContext를 사용하여 MainThread로 전환합니다. 

(withContext는 코루틴의 컨텍스트 전환을 차단하고 있습니다).

 

fun triggerLiveSetWithContextData() {
    viewModelScope.launch(Dispatchers.Default) {
        repeat(10) {
            delay(1000)
            withContext(Dispatchers.Main) {
                ++_liveDataSetWithContext.value
            }
        }
    }
    Thread.sleep(3000)
}

사용 중인 MainThread를 기다리는 처음 3초 동안에는 MainThread가 사용 중이기 때문에 데이터가 방출되지도 않습니다. 

withContext로 인해 백그라운드 스레드가 진행되는 것도 차단하고 있습니다. 

값은 확실히 캐시되거나 표시되지 않습니다.


그러나 MainThread가 해제되면 값을 내보내고 캐싱하고 그에 따라 1에서 10까지 표시하기 시작했습니다. 

손실되는 것은 없지만 전체 프로세스는 아무 작업도 하지 않고 처음 3초 동안 지연됩니다.
간단히 말해 주 스레드가 사용 중일 때 값이 내보내지지 않고 캐시되거나 표시되지 않습니다. 

무료가 된 후에야 전체 프로세스가 계속됩니다. 따라서 손실되는 것은 없지만 프로세스가 지연됩니다.

 

4. LiveData with SetValue using Launch

여기서는 LiveData의 setValue를 사용합니다. 

MainThread에 있어야 하므로 Launch를 사용하여 MainThread로 전환합니다. 

(참고 시작은 코루틴의 비차단 컨텍스트 전환입니다).

 

fun triggerLiveSetWithContextData() {
    viewModelScope.launch(Dispatchers.Default) {
        repeat(10) {
            delay(1000)
            launch(Dispatchers.Main) {
                ++_liveDataSetWithContext.value
            }
        }
    }
    Thread.sleep(3000)
}

사용 중인 MainThread를 기다리는 처음 3초 동안 데이터는 여전히 방출되고 캐시될 수 있습니다. 

시작으로 인해 백그라운드 스레드가 진행되는 것을 차단하지도 않습니다. 

MainThread가 해제되면 그에 따라 3에서 10으로 표시되기 시작했습니다.

초기 값은 손실되지만 전체 프로세스가 지연되지 않습니다.
간단히 말해서 값이 내보내지고 캐시될 수 있지만 표시되지는 않습니다. 

방출된 값은 전혀 손실되지 않지만 표시되지 않을 뿐입니다.
이 동작은 StateFlow와 동일하게 보입니다!

 

 

 

 

참조 :

해당글을 번역기로 돌린것 입니다.

https://medium.com/mobile-app-development-publication/explore-livedata-stateflow-value-emitting-behavior-3f5c9e8ef2e3

반응형