안드로이드

[안드로이드] StateFlow 알아보기

이손안나 2022. 10. 19. 22:50

💡 StateFlow ?

StateFlow와 SharedFlow는 흐름에서 최적으로 상태 업데이트를 내보내고 여러 소비자에게 값을 내보낼 수 있는 flow api

- Flow는 일반적으로 cold stream이지만, StateFlow hot stream다. 그러므로 일반 Flow는 마지막 값의 개념이 없고 collect 될 때만 활성화 되는 반면 StateFlow는 마지막 값의 개념이 있으며 생성하자마자 활성화 된다.

class CounterModel {
    private val _counter = MutableStateFlow(0) // private mutable state flow
    val counter = _counter.asStateFlow() // publicly exposed as read-only state flow 
    
    fun inc() {
        _counter.value++
    }
}

 - stateFlow에는 라이프 사이클에 따라 자동으로 중지되는 기능이 없기 때문에 뷰에서 lifecycleScope를 이용해서 

생명주기를 인지 시켜줘야함. -> lifecycle-livedata-ktx의 .asLiveData()를 통해 해결

 viewModel.userName.asLiveData().observe(viewLifecycleOwner) { 
            userName -> userNameLabel.text = userName
        }

💡 Flow ?

flow는 코루틴을 기반으로 빌드되며 비동기식으로 값을 제어할 수 있는 반응형 스트림
  • coroutineScope내에서 작동
  • 생명주기를 감지하지 못해서 repeatOnLifecycle과 같은 함수를 사용하여 알려줘야 함
  • cold stream 이며 상태가 없음 (value의 형태로 값 얻기 불가능)

💡 LiveData ?

  • activity, fragment 등의 컴포넌트 생명주기를 인식 가능
  • 메모리 누수가 없음

❗️ repository에서는 flow를 사용하고 ui와 repository를 엮는 viewmodel에서는 livedata 사용하기 추천.

 

ex)

class NewsRemoteDataSource(
    private val newsApi: NewsApi,
    private val refreshIntervalMs: Long = 5000
) {
    val latestNews: Flow<List<ArticleHeadline>> = flow {
        while(true) {
            val latestNews = newsApi.fetchLatestNews()
            emit(latestNews) // Emit으로 새로운 값을 데이터 스트림에 방출
            delay(refreshIntervalMs)
        }
    }
}

// 비동기로 뉴스 가져오기
interface NewsApi {
    suspend fun fetchLatestNews(): List<ArticleHeadline>
}
// 중개자
val favoriteLatestNews: Flow<List<ArticleHeadline>> =
	newsRemoteDataSource.latestNews
    	// Intermediate operation to filter the list of favorite topics
        .map { news -> news.filter { userData.isFavoriteTopic(it) } }
        // Intermediate operation to save the latest news in the cache
        .onEach { news -> saveInCache(news) }

//소비자
viewModelScope.launch {
	newsRepository.favoriteLatestNews.collect { favoriteNews ->
    	// Update View with the latest favorite news
   }
}