일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
Tags
- 수성구맛집
- 범물동
- 안드로이드
- 파이썬
- 대구맛집
- 범물동카페
- 안드로이드앱
- Android
- 애드몹
- 의무경찰
- 안드로이드앱개발
- 개발자
- 코딩공부
- 코딩
- 동성로맛집
- 대구카페
- 어플개발
- 동성로핫플
- androidstudio
- 애드센스
- 대구인스타핫플
- 안드로이드개발
- 안드로이드스튜디오
- 감성카페
- 수성구카페
- 인스타핫플
- 동성로카페
- 대구핫플
- 지산동카페
- 앱개발
Archives
- Today
- Total
Glacier's Daily Log
'Flow' in Android 본문
반응형
- Flow?
- Coroutine 비동기 작업에서 Suspend 함수를 사용하여 작업이 모두 완료된 후에 값을 리턴받을 수 있다.
- 하지만 중간에 진행되는 작업 중에 갱신되는 값들도 계속 받을 수 있다면 업데이트를 조금 더 다이나믹하게 진행할 수 있지 않을까?
- Flow를 사용해서 연속적인 값을 방출하게 구현할 수 있다.
- LiveData vs Flow
- 기존에 사용하던 LiveData와 Flow의 차이점?
- LiveData- 생명주기를 가진 데이터 홀더
- 메인스레드에서 동작. 별도 쓰레드에서 동작해야 하는 상황 (Data Layer에서의 구현 등) 에서는 사용하기 어려움
- 안드로이드 의존성이 밀접하게 결합되어 있어 테스트가 힘들다.- 마찬가지로 안드로이드 의존성이 있기 때문에 코드 분리시에 조심해서 사용해야함 - Flow- Coroutine 스코프 내에서 동작. lifecycleScope/viewmodelScope와 사용하면 생명주기에 맞춰서 적절한 동작 구현 가능
- 코틀린 기능이라 안드로이드 의존성이 없다 → 테스트 용이성, 코드 분리시 적절하게 활용 가능
- Cold Stream → collect시에 값이 방출된다.
- LiveData와 다르게 상태가 없다.
- LiveData- 생명주기를 가진 데이터 홀더
- 기존에 사용하던 LiveData와 Flow의 차이점?
- 데이터 스트림 처리
- Producer
- flow {} 블럭 내에서 emit()을 통해서 데이터 생성
- Local/Remote DataSource 등에서 데이터를 생성함
- Intermediary
- 생성된 데이터를 원하는 형태에 맞게 가공함
- 대표적으로 방대한 데이터에서 필요한 데이터만 뽑아 객체로 만드는 등의 작업이 있음.
- map, filter, onEach 등의 메소드를 주로 사용.
- Consumer
- collect를 통해서 데이터 스트림을 소비함
- viewmodel에서 collect하여 View에 뿌려주는 등의 작업이 진행될 수 있음.
- Producer
- Flow 지원 메소드
- collect {} → 데이터를 수집
- collectIndexed → 데이터를 index와 함께 수집 (param : index, value)
- collectLatest → 가장 최근의 데이터를 수집
- .flowOn(Dispatchers.IO).collect {} → 기존 코루틴은 withContext(Dispatchers.IO) 와 같이 디스패쳐를 변경했지만
Flow에서는 .flowOn(DISPATCHER) 로 변경할 것을 권장.
- StateFlow?
- Why StateFlow instead of LiveData?
- LiveData도 충분히 사용하기 좋은 데이터 홀더이지만 아키텍처 관점에서 다소 단점이 있음.
- LiveData는 Android 플랫폼에 의존성이 있다. 따라서 UI가 없는 곳에서 LiveData를 사용할 수 없음.
- 클린아키텍처를 따르려 Domain Layer/Data Layer 분리시에 LiveData를 사용하는데 한계가 있음.
또한 코드 계층을 분리할 때 LiveData가 있는 코드로는 안드로이드 의존성을 떼어내기가 매우 어려움. - 심지어 LiveData는 UI와 밀접하게 연관되어 있어 오직 메인스레드 에서만 읽고 쓸 수 있다. 비동기 스트림 불가.
- Coroutine이 발전하면서 Flow가 등장하게되었고 LiveData를 대체할 수 있는 StateFlow와 SharedFlow라는 대안이 생김.
- StateFlow/SharedFlow는 Hot Stream이다.
- 하나 이상의 소비자들이 구독할 수 있고, 기본값을 가지고 모든 구독자에게 같은 데이터를 발행하며, 구독자가 없는 경우에도 데이터를 발행함.
- 생성하자마자 바로 활성화되며, 값이 업데이트 된 경우에만 반환.
- Why StateFlow instead of LiveData?
class MyViewModel {
private val _myUiState = MutableStateFlow<Result<UiState>>(Result.Loading)
val myUiState: StateFlow<Result<UiState>> = _myUiState
// Load data from a suspend fun and mutate state
init {
viewModelScope.launch {
val result = ...
_myUiState.value = result
}
}
}
-
- stateIn Flow extension 활용하여 더 간단하게 사용하기
val userFlow: StateFlow<UiState> = userRepository
.getUsers()
.asResult()
.map { result ->
when (result) {
is Result.Loading -> UiState.Loading
is Result.Success -> UiState.Success(result.data)
is Result.Error -> UiState.Error(result.exception)
}
}
.stateIn(
scope = viewModelScope,
initialValue = UiState.Loading,
started = SharingStarted.WhileSubscribed(DEFAULT_TIMEOUT)
)
- - 참고 :
StateFlow & SharedFlow에 대한 고찰
StateFlow와 SharedFlow에 관한 잘 정리된 문서가 존재하지만, 해당 포스트에서는 적절한 hot flow를 어떻게 선택할 지에 대한 몇가지 아이디어를 제시하고자 한다.
velog.io
- repeatOnLifecycle(Lifecycle.State.STARTED)로 리소스 낭비 방지하기
- repeatOnLifecycle(Lifecycle.State.STARTED) {} 블록 내의 코드는 라이프사이클이 STARTED와 STOPPED내에 있을 때 Flow를 수집.
- 따라서 원치않는 생명주기에 리소스 낭비를 방지할 수 있음.
반응형
'Coding > Android' 카테고리의 다른 글
UI 작성시 ConstraintLayout을 활용을 권장하는 이유 (1) | 2024.01.25 |
---|---|
runCatching { } 과 Result Type (0) | 2024.01.24 |
무심코 쓴 getApplicationContext()에 대해서 알아보자 (feat. Dialog에 applicationContext 쓰면 안되는 이유) (0) | 2023.07.11 |
코틀린 스코프 함수 알아보기 (Kotlin Scope Function - let, run, with, apply, 그리고 also) (0) | 2023.07.08 |
심플한 무료 태블릿 메뉴판 개발기 : 더메뉴, 스마트메뉴판 (0) | 2023.03.27 |
Comments