Skip to content

〰️ Flow 이모저모

saeyoung Oh edited this page Nov 19, 2023 · 1 revision

이번 프로젝트를 시작하면서 Flow 를 제대로 적용해보자고 다짐했다.
기본적인 사용법을 정리하는 것은 큰 의미가 없다고 생각해, 지금까지 Flow 를 쓰면서 어려움을 겪거나 고민한 부분을 중심으로 기록해보려 한다.



collect vs collectLatest

  • collect
    • collect 는 suspend 함수를 사용하여 emit 된 이벤트를 순차적으로 소비
    • emit 속도 > collect 속도라면, 데이터의 소비가 느려질 수 있음
    • 새로운 데이터가 발행되어도, 이전의 데이터를 먼저 순차적으로 소비함.

  • collectLatest

    • 새로운 데이터가 발행되면 이전의 데이터처리를 멈추고 새로운 데이터를 소비
    • 즉 최신 데이터를 이용하여 UI 를 구현해야하는 상황에 주로 사용되는 연산자
    public suspend fun <T> Flow<T>.collectLatest(action: suspend (value: T) -> Unit) {
        /*
         * Implementation note:
         * buffer(0) is inserted here to fulfil user's expectations in sequential usages, e.g.:
         * ```
         * flowOf(1, 2, 3).collectLatest {
         *     delay(1)
         *     println(it) // Expect only 3 to be printed
         * }
         * ```
         *
         * It's not the case for intermediate operators which users mostly use for interactive UI,
         * where performance of dispatch is more important.
         */
        mapLatest(action).buffer(0).collect()
    }

(참고)[https://kotlinworld.com/252]



SharedFlow 의 파라미터

  • replay
    • 새로운 수신자(subscriber)가 등록될 때 이전 이벤트를 재생하는지 여부.
    • 즉 최신의 이벤트만 처리하고 싶으면 값을 0으로 주어야 함.
    • 데이터를 collect 할 때 전달받을 이전의 데이터 개수를 설정할 수 있고 몇 개를 캐싱하고 있을 지를 인자로 제공해야 함.
  • extraBufferCapacity
    • buffer 개수 정하는 옵션.
    • flow의 emit이 빠르고 collect가 느릴 때 지정된 개수만큼 buffer에 저장되며 지정된 개수가 넘어가면 onBufferOverflow 정책에 따라 동작.
  • onBufferOverflow
    • buffer 가 다 찼을 경우 정책.
      • SUSPEND : emit 코드가 blocking
      • DROP_OLDEST : 버퍼 안의 오래 된 데이터부터 삭제
      • DROP_LATEST : 버터 안의 최신 데이터부터 삭제

  • 문제 경험

    • sharedFlow 로 MyPageFragment -> EditProfileFragment (NavigateToEditProfile event), EditProfileFragment -> MyPageFragment (NavigateToBack event) 로 관리하고 있었음. 이때 NavigateToEditProfile로 EditProfileFragment 에 이동해서 NavigateToBack 를 트리거하면 back 동작이 실행되지 않음.

    • replay 옵션을 1로 주고 있어서, 이전의 event 1개가 캐싱되고 있었고, 그래서 NavigateToBack 와 함께 NavigateToEditProfile도 받아오는 것이 원인.

    • sharedFlow replay 파라미터를 1 -> 0 으로 변경하니 문제가 해결됨.
Clone this wiki locally