반응형
안녕하세요
날씨가 많이 더워지고 있네요.. 덥다보니 축 처지게 되는데.. 학습을 게을리 하지말고
하루하루 배우는 시간이 되게 해야겠습니다

오늘은 Android에서 사용되는 StateFlow에 대해 포스팅하려 합니다.
StateFlow에 대해 학습하려면, Flow에 대해 먼저 하시면 이해에 도움이 되실 것 같습니다.
StateFlow란?
StateFlow란
- 특정 State를 유지, 관찰
- Collector에 현재와 새로운 State를 업데이트
- 현재 State 값은 StateFlow.value로 읽을 수 있습니다.
class LatestNewsViewModel(
private val newsRepository: NewsRepository
) : ViewModel() {
// 다른 클래스의 상태 업데이트를 방지하기 위한 백업 속성
private val _uiState = MutableStateFlow(LatestNewsUiState.Success(emptyList()))
// UI는 상태 업데이트를 위해 StateFlow를 수집합니다.
val uiState: StateFlow<LatestNewsUiState> = _uiState
init {
viewModelScope.launch {
newsRepository.favoriteLatestNews
// 최신 인기 뉴스로 보기 업데이트
// MutableStateFlow의 value 속성에 기록하여 흐름에 새 요소를 추가하고 모든 수집기를 업데이트합니다.
.collect { favoriteNews ->
_uiState.value = LatestNewsUiState.Success(favoriteNews)
}
}
}
}
// LatestNews 화면에 다양한 상태를 나타냅니다.
sealed class LatestNewsUiState {
data class Success(val news: List<ArticleHeadline>): LatestNewsUiState()
data class Error(val exception: Throwable): LatestNewsUiState()
}
- StateFlow는 LatestNewsViewModel에서 출력될 수 있습니다.
- 따라서, View 상태 업데이트를 수신할 수 있고, 기본적으로 화면 상태가 구성 변경을 유지하도록 합니다.
- MutableStateFlow의 업데이트를 담당하는 클래스가 Producer 입니다.
- StateFlow를 수집하는 모든 클래스들은 Consumer 입니다.
- flow 빌더를 사용하여 구축하는 cold flow 와는 달리, StateFlow는 Flow에서 수집하여도 Producer가 트리거되지 않습니다. > hot flow
- StateFlow는 항상 Active 상태이고 메모리에 있습니다.
- 가비지 컬렉션 루트에서 이에 대한 다른 참조가 없는 경우 가비지 컬렉션 대상이 됩니다.
- 새로운 Customer가 Flow로부터 수집을 시작할 때, 스트림의 마지막 상태와 후속 상태를 전달받습니다.
- View는 다른 Flow와 마찬가지로 StateFlow를 수신합니다.
class LatestNewsActivity : AppCompatActivity() {
private val latestNewsViewModel = // getViewModel()
override fun onCreate(savedInstanceState: Bundle?) {
...
//수명 주기 범위에서 Coroutine을 시작합니다.
lifecycleScope.launch {
// repeatOnLifecycle 수명 주기가 STARTED 상태에 있을 때마다
// 새 Coroutine에서 블록을 시작하고 STOPPED 일 때 취소합니다.
repeatOnLifecycle(Lifecycle.State.STARTED) {
// Flow를 트리거하고, 값을 수신합니다.
// 수명 주기가 STARTED일 때 발생하고, STOPPED일 때 중지됩니다.
latestNewsViewModel.uiState.collect { uiState ->
// 새로운 값 수신
when (uiState) {
is LatestNewsUiState.Success -> showFavoriteNews(uiState.news)
is LatestNewsUiState.Error -> showError(uiState.exception)
}
}
}
}
}
}
- UI를 업데이트 해야 하는 경우, launch (또는 launchIn) 확장 기능에서 직접 UI에서 Flow를 수집하면 안됩니다.
- View가 보이지 않는 경우에도 이벤트를 처리합니다.
- 이 동작은 앱 충돌로 이루어 질 수도 있습니다.
- 임의의 flow를 StateFlow를 변환하기 위해서, stateIn 을 사용합니다.
StateFlow, Flow, LIveData
- 공통점
- StateFlow와 LiveData는 서로 유사합니다.
- 두 관찰가능한 데이터 홀더 클래스
- 앱 아키텍처에 사용될 때 간단한 패턴을 따릅니다.
- 다른점
- StateFlow는 생성자에 초기 상태를 요청하지만, LiveData는 해당 기능이 없습니다.
- LiveData.observe()는 view가 STOPPED 상태가 되면 자동으로 Consumer 등록을 취소합니다.
- StateFlow나 다른 flow를 수집해도 자동 중지는 되지 않습니다.
- LiveData로 유사한 기능을 구현하려면, Lifecycle.repeatOnLifecycle 블록에서 Flow를 수집합니다.
shareIn을 사용하여 cold flow를 hot으로 만들기
- 새 Flow를 생성하는 대신 shareIn을 사용하여 수집기 간에 Firestore에서 검색된 데이터를 공유할 수 있습니다.
class NewsRemoteDataSource(...,
private val externalScope: CoroutineScope,
) {
val latestNews: Flow<List<ArticleHeadline>> = flow {
...
}.shareIn(
externalScope,
replay = 1,
started = SharingStarted.WhileSubscribed()
)
}
- 전달해야하는 것들
- CoroutineScope : Flow를 공유하는데 사용됩니다.
- 범위는 공유된 Flow가 필요한 만큼 오래 유지하기 위해 Customer 보다 오래 있어야 합니다.
- 각각의 새 수집기에 재생할 항목 수
- 시작 동작 정책
- CoroutineScope : Flow를 공유하는데 사용됩니다.
오늘은 StateFlow에 대해서 알아보았습니다.
반응형
'DEV > Android' 카테고리의 다른 글
[TIL-230706] Jetpack Compose - Focusing (1) | 2023.07.06 |
---|---|
[TIL-230705] Google Map - 지도 출력시 마지막 위치로 시작하기 (Jetpack Compose) (0) | 2023.07.05 |
[TIL-230626] Android Flow 알아보기 - 2 (0) | 2023.06.27 |
[TIL-230626] Android Flow 알아보기 - 1 (0) | 2023.06.26 |
[TIL-230625] Android Coroutine 알아보기 (0) | 2023.06.25 |