일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
31 |
- Hilt
- coroutine
- Koin
- 안드로이드 아키텍처 컴포넌트
- 안드로이드 테스트코드
- 안드로이드 앱 아키텍처 가이드라인 예시
- 안드로이드 앱 아키텍처 가이드라인 설명
- 안드로이드 Espresso
- android DI
- 안드로이드 mvvm예제
- 안드로이드 의존성주입
- MVVM
- sharedFlow
- 안드로이드 JUnit
- Android MVVM
- 안드로이드 mvvm
- 안드로이드 최적화
- 안드로이드 클린 아키텍처
- 안드로이드 앱 아키텍처 가이드라인 사용법
- Android App Architecture Guideline
- 안드로이드 앱 아키텍처 가이드라인
- RxJava
- android memory leak
- 리싸이클러뷰 최적화
- 안드로이드 리싸이클러뷰
- 스타트업 코딩테스트
- android clean architecture
- 코루틴
- 안드로이드 hilt
- 안드로이드 Mockito
- Today
- Total
안드로이드 연구소
Flow 심화1: StateFlow와 SharedFlow 본문
안녕하세요. 한 두달만에 등장하였습니다!
저는 추석 끝난 후 이직을 하여 새로운 회사로 출근하여
약 한달간 워크샵이랑 회사 서비스 코드를 파악하면서 시간을 보냈습니다.
그러던 중에 회사 서비스 코드에 LiveData가 없다는 사실을 알게되었습니다.
그러면 LiveData대신에 어떻게 작성을 하였을까요?
그건 바로 Flow를 사용해서 LiveData를 대신하여 데이터를 사용하고 있었습니다.
꽤 최근에 LiveData로 작성되있던 코드들을 Flow를 바꾸었다고 했다는데
Flow에 어떤 장점이 있었기 때문에 그랬을까요?
그에 대한 대답을 하기 전에 저희 회사 안드로이드 팀장님이 주신 포스트를 보면
히스토리를 더욱 잘 알 수 있습니다.
(킹갓 또상권: 박상권 짱짱맨)
MVVM의 ViewModel에서 이벤트를 처리하는 방법 6가지
지금 개발하시는 코드에서 ViewModel의 이벤트 처리를 어떻게 하고 계신가요? 헤이딜러에서 LiveData -> SingleLiveData -> SharedFlow -> EventFlow로 이벤트 처리 방법을 변화 하기까지 과정을 소개합니다…
medium.com
0. 단일 이벤트 처리
안드로이드에서는 토스트 메시지 표시, 다른 화면으로 이동, 스낵바 표시 등과 같은
해당 경우에 한번만 보여줘야하는 일회성 UI 작업을 나타내야하는 경우가 많습니다.
단순히 LiveData 사용하여 ViewModel에서 따라 토스트 메시지, 스낵바 표시를 해주는 로직을 만들었다면
이벤트가 발생했을 때 한번 발생한 후에 한참 뒤에 화면 회전을 한다면
다시 토스트 메시지나 스낵바가 다시 표시될 수 있습니다.
이렇기 때문에 우리는 단일 이벤트 처리를 할 수 있도록 ViewModel에서 세팅을 해야합니다.
1. LiveData+Event
그래서 Event wrapper를 사용해서
단일 이벤트가 이전에 실행되지 않는 경우에만 콜백 메서드를 실행시켜줄 수 있습니다.
자세한 사용 방법은 아래 블로그를 추천합니다.(우리의 목적지는 Flow! 갈 길이 멀다.)
https://leveloper.tistory.com/200
[Android] Event Wrapper를 사용한 단일 이벤트 처리
MVVM 패턴에서 ViewModel은 View에 대한 직접적인 참조를 할 수 없습니다. 이때 ViewModel에서 View의 이벤트를 전달해주기 위해선 어떻게 해야 할까요? 간단한 예를 들어보겠습니다. ViewModel에서 데이터
leveloper.tistory.com
2. SingleLiveData
그 후에 Event wrapper가 아래처럼 사용하기가 귀찮았는지 안이뻐보였는지
SingleLiveData로 깔끔하게 사용할 수 있게하였습니다.
LiveData<Event<String>>
MutableSingleLiveData<String>()
3. Flow등장(SharedFlow)
드디어 등장한 오늘의 주인공 Flow.
만들어진지 3년뒤쯤인 2021~2022년 즈음에 Flow는 많은 안드로이드 개발자에게 LiveData 대신 사랑을 받게 됩니다.
그 이유를 이전 저의 글에서는 Flow에서 데이터 스트림과 연산자이기 때문이라고 이야기했습니다.
하지만 위 포스트에서는 다른 이유로 Flow를 선택하게되었는데요.
클린 아키텍처 패턴 관점에서는 ViewModel에서는 특정 플랫폼에 관계없이 사용할 수 있어야기 때문에
아래처럼 android를 호출하는 코드가 없어야합니다.
import android.xxx
ViewModel에서 LiveData를 사용하게된다면 아래 import들이 남게됩니다.
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
하지만 Flow를 사용하게된다면 아래처럼 안드로이드 플랫폼에 종속되지 않을 수 있습니다.
Flow는 Coroutine의 기능 중 하나이고, Coroutine은 Kotlin의 기능이기 때문이지 않을까 싶습니다.
(이 이유가 아니라면 댓글 부탁드립니다. 제발~)
import kotlinx.coroutines.flow.Flow
다시 Flow로 넘어가게되면
LiveData는 StateFlow로
SingleLiveData는 SharedFlow로 사용할 수 있게 되었습니다.
또 observe함수 대신에 Collect를 사용해주면 됩니다.
3-1. StateFlow와 SharedFlow
둘 다 관찰 가능한 상태 홀더 흐름입니다
StateFlow
- 상태를 유지하고 상태가 변경될 때마다 이를 수집기로 내보내도록 설계되었습니다.
- UI 컴포넌트는 StateFlow를 관찰하여 상태 변경에 반응하고 그에 따라 UI를 업데이트할 수 있습니다.(ex, 로딩, 오류, 성공 상태)
import kotlinx.coroutines.flow.MutableStateFlow
val stateFlow = MutableStateFlow("Initial State")
// To update the state
stateFlow.value = "New State"
// To collect the state
stateFlow.collect { state ->
// Handle the state change
}
SharedFlow
- SharedFlow는 여러 수집기가 방출된 값을 수신할 수 있도록 하는 HotStream입니다.
- (단일 값 보유자인 StateFlow와 달리) SharedFlow는 여러 값을 내보내며 여러 소비자가 동시에 수집할 수 있습니다.
- 프래그먼트, 서비스 또는 백그라운드 작업과 같은 다양한 구성 요소 간에 이벤트를 전달하는 데 사용할 수 있습니다.
import kotlinx.coroutines.flow.MutableSharedFlow
val sharedFlow = MutableSharedFlow<String>()
// To emit values to the flow
sharedFlow.emit("Value 1")
sharedFlow.emit("Value 2")
// To collect values from the flow
sharedFlow.collect { value ->
// Handle the emitted value
}
https://developer.android.com/kotlin/flow/stateflow-and-sharedflow?hl=ko
StateFlow 및 SharedFlow | Kotlin | Android Developers
StateFlow 및 SharedFlow 컬렉션을 사용해 정리하기 내 환경설정을 기준으로 콘텐츠를 저장하고 분류하세요. StateFlow와 SharedFlow는 흐름에서 최적으로 상태 업데이트를 내보내고 여러 소비자에게 값을
developer.android.com
3-2. Collect vs CollectLastest
collect
- 이전 데이터가 끝난 후에 다음 데이터를 처리한다.
collectLatest
- 새로운 데이터가 들어오면 이전 데이터를 종료시키고 새로운 데이터를 처리한다.
- 최신 데이터만 UI에 보여줘도 될 경우 적합
[Coroutine Flow] collect와 collectLatest의 차이는 무엇인가?
collect를 사용한 데이터 소비의 한계점 Flow는 Coroutine상에서 Reactive한 프로그래밍을 할 수 있도록 만들어진 데이터 파이프 라인이다. Flow는 데이터를 발행하는 역할을 하며 Flow에서 발행하는 데이
kotlinworld.com
3-3. 정리
MutableSingleLiveData+Observe 대신에 SharedFlow+Flow를 사용하면 됩니다.
이전 viewModel: MutableSingleLiveData
private val _showToastEvent = MutableSingleLiveData<String>()
val showToastEvent: SingleLiveData<String> = _showToastEvent
이후 viewModel: MutableSharedFlow
private val _showToastEvent = MutableSharedFlow<String>()
val showToastEvent = _showToastEvent.asSharedFlow()
이전 UI(Activity, Fragment): observe
viewModel.showToastEvent.observe { text ->
// TODO
}
이후 UI(Activity, Fragment): collect
lifecycleScope.launch {
viewModel.showToastEvent.collect { text ->
// TODO
}
}
다음 게시물에서 4~6단계 계속!
'안드로이드 연구소 > 비동기' 카테고리의 다른 글
Flow 심화2: EventFlow (1) | 2023.11.13 |
---|---|
[Flow vs RxJava] Flow(Coroutine Flow) (0) | 2023.06.07 |
안드로이드 코틀린 코루틴(coroutine) (1) | 2023.05.09 |