✅ Coroutine StateFlow
안드로이드 프로젝트 구조를 MVVM으로 설계를 하면서 LiveData를 정말 편하게 잘 활용해왔다.
거의 필수적으로 사용했던 이유를 추려보자면 다음과 같을 것이다.
1. LiveData는 Activity, Fragment등의 Android Component의 Lifecycle을 자동으로 인식한다.
2. Observer Pattern으로 구현되어 관찰하고 있는 데이터가 변경되면 Observer 객체에 알려주고 이를 이용해서 UI를 업데이트 할 수 있다.
3. AAC DataBinding과 호환되어 사용하기 매우 편리하다.
이러한 LiveData의 한계점도 있을까?
Andorid 환경에서 통용되는 Clean Architecture를 생각해보자.

- Presentation Layer는 View, ViewModel 등 화면의 입출력과 같은 UI를 담당한다고 보면된다. LiveData의 인스턴스 및 객체는 ViewModel에서 관리된다.
- Domain Layer는 비즈니스 로직에 필요한 UseCase나 Entity Model등을 포함한다. 중요한 것은 안드로이드 프레임워크에 의존성을 가지지 않은 순수한 Java/Kotlin코드로만 구성된다.
- Data Layer에는 Local/Remote Database와의 통신이 발생한다. API Interface, DataSource, DTO 및 Mapper등이 여기에 해당한다.
>> LiveData는 Presentation Layer에서는 문제없이 잘 작동한다. 하지만 Data Layer나 Domain Layer에서는 그렇지 않을 확률이 높다. 비동기 데이터 스트림 처리가 불가능하고, 어떤 방법으로 처리하더라도 관찰은 MainThread에서만 가능하기 때문이다.
그래서 개발자들 사이에서 Flow가 LiveData를 대체할 수 있을까?에 관한 이야기가 나왔지만,
- Stateless -> 상태가 없어 현재의 값을 정확히 알 수 없다.
- Declarative Cold Stream -> cold stream 방식으로 collect 되었을 때만 데이터를 생성하고 값을 반환한다.
- Doesn't know Android Lifecycle -> Flow는 자체적으로 안드로이드의 수명주기를 알지 못한다이러한 Flow의 특성으로 Live Data를 완벽하게 대체할 수 없었고, 이 대안으로 StateFlow와 SharedFlow가 나왔다.
✅ StateFlow
StateFlow는 현재상태와 새로운 상태를 collector에게 알려주기 때문에 Observable하다.
value 프로퍼티를 이용하여 현재 상태 값을 알 수 있다.
StateFlow는 다음과 같은 특징이 있다.
- 항상 값을 가지고 있고, 오직 한가지 값을 가진다.
- 여러 개의 collector를 지원하고 그 갯수에 상관없이 항상 구독하고 있는 것의 최신 것을 받는다.
- Flow는 Cold Stream인데 반해 StateFlow는 Hot Stream이다. collector에서 수집하더라도 새로운 생성자가 트리거 되지 않는다.
@HiltViewModel
class ClassDashBoardViewModel @Inject constructor(
private val fetchScheduleUseCase: FetchScheduleUseCase
): ViewModel() {
private val _reservedSchedule = MutableStateFlow<ReservedScheduleEntity?>(null)
val reservedSchedule: StateFlow<ReservedScheduleEntity?> = _reservedSchedule.asStateFlow()
fun fetchSchedule() {
viewModelScope.launch {
val schedules = fetchScheduleUseCase()
if (schedules is ApiResult.Success) {
schedules.data?.let {
_reservedSchedule.value = it
}
} else {
Log.e("error","fetch schedules")
}
}
}
}
LiveData만 StateFlow로 바꿨지 사용하는 방식은 거의 비슷하다.
그렇다면 뷰에서는 어떻게 stateflow의 값을 관찰하는지 봐보자.
lifecycleScope.launchWhenStarted {
viewModel.reservedSchedule.collect {
viewModel.fetchUserProfile()
}
}
LiveData는 AAC의 생명주기에 따라 자동으로 Observer의 등록을 취소하는 반면 SateFlow는 collect를 자동으로 중지하지 않는다. 때문에 lifecycleScope를 이용하여 생명주기를 인지시켜줘야 한다.
StateFlow의 연산자와 활용방법에 대해 더 공부해봐야겠다.
<참고자료>
https://yoon-dailylife.tistory.com/72
Android) 코루틴 StateFlow와 SharedFlow 알아보기 및 LiveData와 비교
최근 코틀린 코루틴 라이브러리 (1.4.1)에서 Stable API로 배포된 StateFlow, SharedFlow가 무엇인지와 이들로 LiveData를 대체할 수 있는지를 알아보려고 합니다. StateFlow 기본적으로 상태 처리를 위한 새로
yoon-dailylife.tistory.com
https://myungpyo.medium.com/stateflow-%EC%99%80-sharedflow-32fdb49f9a32
StateFlow 와 SharedFlow
코루틴 공식 가이드 읽기 Part 9 — Dive1
myungpyo.medium.com
'Coroutines' 카테고리의 다른 글
| [Coroutines] Channel, Pipeline (0) | 2022.02.10 |
|---|---|
| [Coroutines] Flow (0) | 2022.02.09 |
| [Coroutines] Job (status, cancel error handling) (0) | 2022.02.08 |
| [Coroutines] Coroutine Basic1 (CoroutineScope, CoroutineContext, Dispatcher, Async, launch) (0) | 2022.02.08 |