Android Kotlin StateFlow and SharedFlow

사용 언어: Kotlin 1.9.22
사용 버전: Kotlin Playground


안드로이드 코틀린 StateFlow and SharedFlow를 알아보겠습니다.



Flow의 하나인 StateFlow와 SharedFlow를 알아보는 시간을 가져봅니다.


공식 문서입니다.
https://developer.android.com/kotlin/flow/stateflow-and-sharedflow


flow에는 cold flow와 hot flow가 있습니다.

cold(콜드) flow는 값을 요청할 때에만 emit(방출) 하는 형식이고,

hot(핫) flow는 값을 요청하지 않아도 혼자서 계속 방출을 하는 형식입니다.



역시 뜨거운 물 샤워는 물 낭비를 하게 되는군요. 크흠.



StateFlow(스테이트 플로)와 SharedFlow(쉐어드 플로)는 hot flow입니다.

StateFlow와 SharedFlow는 state(상태) update(최신화)와 여러 consumers(컨슈머)에게 값을 emit 하기 위해 사용합니다.

그리고 SharedFlow는 세부적 설정이 가능한 StateFlow입니다.



⊙ StateFlow; 스테이트 플로:

value를 호출함으로 현재 state 값을 읽을 수 있습니다. 새로운 값을 넣기 위해서는 MutableStateFlow에 value 값을 새로운 값으로 넣어주면 됩니다.



아래는 예시입니다.




MutableStateFlow는 Producer(생산자)가 되고, StateFlow는 Consumers(소비자)가 됩니다.

StateFlow는 hot이므로 collect(콜렉트)가 producer code를 실행하지 않습니다.

StateFlow는 항상 in memory(메모리)에서 작동합니다.



새로운 consumer가 collect(수집)을 하게 되면, 항상 마지막 값을 반환합니다. 이것은 LiveData와 동일한 동작입니다.





• 주의: UI의 Update가 필요한 곳에서 launch 또는 launchIn을 사용하여 UI에서 직접적으로 flow를 collect 하면 안 됩니다. UI가 보이지 않더라도 계속해서 업데이트하게 됩니다. 앱의 오류를 발생시킵니다. 이것을 피하려면 위처럼 repeatOnLifecycle API를 사용해야 합니다.





flow를 stateIn을 사용하여 StateFlow로 변환할 수 있습니다.









• StateFlow, Flow, and LiveData; StateFlow, Flow, 그리고 LiveData:

StateFlow와 LiveData는 비슷합니다. 추적이 가능한 data(데이터) holder(홀더) classes(클래스)입니다. 그리고 앱에서 같은 패턴으로 사용됩니다.



하지만, 행동에 차이점이 있습니다.

  - StateFlow는 초깃값이 항상 필요합니다. LiveData는 초깃값이 필요 없습니다.

  - LiveData.observe()는 자동으로 STOPPED에서 해제됩니다. StateFlow나 다른 flow들은 collect를 자동으로 멈추지 않습니다. 같은 행동을 하기 위해서는 Lifecycle.repeatOnLifecycle 구문을 사용합니다.



⊙ Making cold flows hot using shareIn; cold 플로를 shareIn으로 hot으로 만들기:

StateFlow는 hot flow입니다. collected 되거나 refrences(레퍼런스)가 garbage collection(가비지 컬렉션) root에 존재하는 한 memory에 계속 남아있습니다. cold flow를 shareIn으로 hot으로 만들 수 있습니다.









collectors끼리 data를 공유할 수 있게 shareIn을 사용하는데 다음의 것들이 필요합니다.

• flow를 공유하는 데 사용할 CoroutineScope. 이 scope(스코프)는 consumer보다 길어야 shared flow가 오랫동안 살아있습니다.

• 새로운 collector에 몇 개의 내용을 다시 보낼지 설정.

• 시작 행동 정책.







여기서 사용된 lastesNews flow는 externalScope가 살아있는 한 계속 존재하며, 새로운 collect에게 마지막 값을 다시 전달합니다. SharingStarted.WhileSubscribed()는 collector가 존재할 때 시작한다는 뜻입니다.  다른 정책으로는 Eagerly, Lazily가 있습니다.











⊙ SharedFlow;:

sharedIn은 SharedFlow를 반환합니다. 모든 consumers가 collect 가능한 hot flow입니다. SharedFlow는 세부 설정이 가능한 StateFlow입니다.



shareIn 없이 SharedFlow를 만들 수 있습니다. 아래 예시는 특정 시간마다 업데이트를 하도록 만드는 SharedFlow입니다. StateFlow처럼 MutableSharedFlow를 backing property로 사용합니다.




당신은 SharedFlow의 설정을 조작할 수 있습니다.

• replay: 새로운 subscribers에게 이전에 emitted 된 것을 다시 보내줍니다.

• onBufferOverflow는 buffer가 꽉 찼을 때의 정책입니다. BufferOverflow.SUSPEND가 기본이고, Buffer가 빌 때까지 보내지 않습니다. 다른 정책 DROP_LAST, DROP_OLDEST가 있습니다.





replay를 좀 더 알아봅시다.

https://pl.kotl.in/fXmC3E4Iz





replay가 2로 설정되었기 때문에 위의 코드를 실행하면, First가 0, 1, 2, 3이 나오고 이제 4가 나올 차례에 Second가 실행되어 Second는 replay를 받아 2, 3, 4가 나오게 됩니다. 그 뒤, First가 4가 나오고 이제 차례대로 Second 5, First 5 이런 식으로 나오게 됩니다. 

위의 링크에서 실행해 보실 수 있습니다.



MutableSharedFlow는 subscriptionCount가 존재하며, collectors의 개수를 조절하여 당신의 business 로직에 최적화 시킵니다. MutableSharedFlow는 또한 resetReplayCache가 존재하여 새로운 flow에 replay를 하지 않게 만들 수 있습니다.






끝.



카테고리: Android






댓글

이 블로그의 인기 게시물

Python urllib.parse.quote()

Python bytes.fromhex()

Python OpenCV 빈 화면 만들기

Android Notification with Full Screen

Android Minimum touch target size

Android Compose Instrumentation test to unit test

KiCad 시작하기 7 (FreeRoute 사용하기 2)

딩기 요트 명칭

tensorflow tf.expand_dims()

Android AVD Ram size change