본문 바로가기
Android & Kotlin/Android

[Android kotlin] 안드로이드 Flow vs LiveData

by 말린밴댕이_공부 2024. 1. 2.
반응형

ViewModel 관리 : Flow vs LiveData

 

LiveData

  • LifeCycle 인식을 통한 Observer 패턴
    • LiveData는 안드로이드의 라이프사이클을 인식하므로 관련된 구성요소가 활성 상태일때만 데이터가 업데이트 되므로 메모리 누수나 비정상적인 UI 갱신을 방지하는데 도움이 된다
    • 데이터가 변경될 때마다 등록된 Observer에게 알림을 보내 UI갱신을 하는 패턴 사용.
1. UI와 데이터 상태의 일치 보장
2. 메모리 누수 없음
3. 중지된 활동으로 인한 비정상 종료 없음
4. 수명 주기를 더 이상 수동으로 처리하지 않음
5. 최신 데이터 유지
6. 적절한 구성 변경 : 기기 회전 혹은 다시 액티비티나 프래그먼트가 생성되면 최신 데이터를 받아옴 
7. 리소스 공유

Flow

코루틴에서 Flow는 단일값을 반환하는 suspend와 달리 값을 순차적으로 보낼 수 있는 유형입니다.

예시로는 Flow를 사용하면 데이터 베이스에서 실시간 업데이트를 수신할 수 있습니다.

  • 생산자는 스트림에 추가되는 데이터를 생산합니다. 코루틴 덕분에 흐름에서 비동기적으로 데이터가 생산될 수도 있습니다.
  • (선택사항) 중개자는 스트림에 내보내는 각각의 값이나 스트림 자체를 수정할 수 있습니다.
  • 소비자는 스트림의 값을 사용합니다.

즉, 코루틴을 기반으로 비동기식으로 값을 제어할 수 있는 콜드 스트림 방식이다.

 

콜드 스트림(Cold Stream):

옵서버가 해당 스트림을 구독할 때마다 처음부터 데이터를 생성하는 스트림입니다. 
각 옵서버는 독립적인 상태를 가지며, 스트림이 여러 번 구독될 때마다 각각의 옵서버에게동일한 데이터가 전달됩니다.

핫 스트림(Hot Stream):

스트림이 생성된 후에 옵서버가 구독하더라도, 
옵서버가 현재 스트림의 어떤 지점에서든지 데이터를 수신할 수 있는 스트림입니다. 
즉, 스트림이 이미 생성되었고 데이터가 흐르고 있는 상태에서 옵서버가 구독하면 
현재의 데이터나 이후의 데이터를 수신할 수 있습니다.

 

차이점

LiveDataFlow와 비교해 라이프 사이클을 관리도 해주며 , 상태를 확인할 수 있으며, Cold Stream의 방식으로 연속해서 들어오는 데이터의 처리를 할 수 없는데

 

Flow를 채택한 이유는 무엇일까?

채택한 이유

Flow는 kotlin라이브러리이며, LiveData는 jetpack에서 제공하므로 Android 플랫폼에 종속적이다.

StateFlow 특징

  1. 현재 상태를 collector에 보내지며 observable 한 홀더 flow
  2. 항상 값을 가지고 있으며 오직 한 가지의 값을 가지며 가장 최신 값을 가져 오는 것이 Flow의 cold Stream과 다르게 Hot Stream 데이터 홀더 클래스

SharedFlow 특징

  1. StateFlow와 달리 값을 가지지x, 초기 값x
  2. Flow의 coldd Stream과 다르게 Hot Stream 데이터 홀더 클래스
  3. 속성 (이전 이벤트 방출할지, 추가 버퍼 생성여부, 버퍼 초과 처리)가 존재

Flow의 단점이었던 repeatOnLifecycle ,launchWhen(Created,Resumed,Started) 과 같이 생명주기를 인식 하지 못한다는 단점을 해결할 수 있다!

 

즉, 아래와 같이 lifeCycle에 따라 수집할지 멈출지 결정을 할 수 있다.

 

 

그럼 우리는 화면 회전과 같이 금방 다시 lifeCycle start를 하게 되면 받아야 하나? → No!

앱이 홈버튼 클릭과 같이 백그라운드로 아예 가버렸는지 잠시 회전을 하였는지 속성들을 통해 정의를 해준다.

 

[좌] 앱을 다시 열 경우 [우] 화면 회전할 경우

 

Repository Response : Flow 사용 이유

앞서 flow에 대해 알아보았고 Repository Response에 Flow를 사용 하는 이유에 대해 알아보겠습니다.

Call ,Response

  • Call 클래스 사용 시 enqueue callback활용과 동기적인 작업에 수행에 사용이 된다.
  • 비동기적인 작업을 수행하기 위해 결과 값 만을 사용하는 Response클래스는

Flow

  • 비동기 데이터 스트림 처리
override fun signup(body: DetailSignupRequest): Flow<BaseState<Unit>> = flow {
        val result = runRemote { api.signup(body) }
        emit(result)
    }
  • 비동기 작업을 중간에 취소 가능 o
override fun signup(body: DetailSignupRequest): Flow<BaseState<Unit>> = flow {
        val result = withContext(Dispatchers.IO){
					 api.signup(body) 
				}
        emit(result)
    }
  • Retrofit과 같은 라이브러리에서 제공하는 비동기 API호출을 FLOW로 감싼다.
override fun signup(body: DetailSignupRequest): Flow<BaseState<Unit>> = florunRemote { api.signup(body)}.asFlow()

 

 

결론

플로우는 안드로이드 종속성을 가지고 있지 않으며, LiveData는 수명 주기와 밀접하게 연관되어 있어서 android 앱의 UI와 잘 통합되는 장점이 있지만, Flow는 비동기 작업을 수행하는 데 Coroutine과 함께 사용되고, map, filter, combine 등의 연산자를 사용하여 데이터 스트림을 변환하거나 조합하는 것이 간편하며, livedata처럼 생명주기에 따라 관리를 할 수 있으며, 다양한 연산을 쓸 수 있다는 장점이 있습니다.

(의존성이 없어 KMP 활용 가능 → 근데 언제쯤..?)

 

위와 같은 이유로 LiveData보다 Flow 를 채택하였고 Repository에서 Flow를 채택하였습니다.

 

 

[레퍼런스]

LiveData 안드로이드 공식문서

Flow 안드로이드 공식문서

StateFlow, SharedFlow 안드로이드 공식문서

kotlin flows in pratice - android youtube

LivaData에서 flow Migration 글

반응형

댓글