[Android] Coroutine Flow[2]๐Ÿค”

ํ‘ธ๋ฅธํ•˜๋Š˜ยท2022๋…„ 8์›” 18์ผ
1

flow

๋ชฉ๋ก ๋ณด๊ธฐ
2/2
post-thumbnail

โœ… Flow vs StateFlow

๐ŸŽ ๊ธฐ์กด Flow ์‚ฌ์šฉ

Flow๋Š” ๋ฐ์ดํ„ฐ์˜ ํ๋ฆ„๋งŒ ๋ฐœ์ƒํ•˜๋ฉฐ ๋ฐ์ดํ„ฐ๊ฐ€ ๋”ฐ๋กœ ์ €์žฅ๋˜์ง€ ์•Š๋Š”๋‹ค

์ด๋Ÿด ๊ฒฝ์šฐ...

๋งŒ์•ฝ ์‚ฌ์šฉ์ž๊ฐ€ ํ™ˆ ํ™”๋ฉด์— ๊ฐ”๋‹ค๊ฐ€ ๋‹ค์‹œ ์•ฑ์„ ๋“ค์–ด์˜จ๋‹ค๋ฉด ๋ฐ์ดํ„ฐ๋Š” ์ดˆ๊ธฐํ™”๋œ๋‹ค
์ด๋ ‡๊ฒŒ ๋˜๋ฉด ์‚ฌ์šฉ์ž๋Š” ๋ดค๋˜ ์„น์…˜ ์ธ๋ฑ์Šค๊นŒ์ง€ ๋‹ค์‹œ ์ฐพ์•„๊ฐ€์•ผ ํ•œ๋‹ค๋Š” ๋ฒˆ๊ฑฐ๋กœ์›€์ด ์ƒ๊ธด๋‹ค

๊ทธ๋ž˜์„œ..

flow์˜ collectํ•œ ๋ฐ์ดํ„ฐ๋ฅผ viewModel์— ์ €์žฅํ•œ๋‹ค.

ํ•˜์ง€๋งŒ...

๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•˜๊ณ  ์žˆ์œผ๋ ค๋ฉด ๋ณ„๋„์˜ ๋ฐ์ดํ„ฐ ํ™€๋” ๋ณ€์ˆ˜๋ฅผ ๋งŒ๋“ค์–ด์•ผํ•˜๋ฉฐ, ์ด๋Ÿฌํ•œ ๋ณ€์ˆ˜๋Š” Reactive ํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— UI์—์„œ ๋”ฐ๋กœ Fetching ๋กœ์ง์„ ๋งŒ๋“ค์–ด์•ผํ•œ๋‹ค.

  • ๋ณด์ผ๋Ÿฌ ํ”Œ๋ ˆ์ดํŠธ ์ฝ”๋“œ ์ƒ์„ฑ
  • ๊ฐ€๋…์„ฑ์„ ๋–จ์–ดํŠธ๋ฆฐ๋‹ค
  • Cold Flow(Stream)

โ„๏ธ Cold Flowโ—๏ธ โ„๏ธ

  • ํ•„์š”์— ๋”ฐ๋ผ ์ƒ์„ฑ๋˜๊ณ  ๊ด€์ฐฐ๋˜๋Š” ์ค‘์—๋งŒ ๋ฐ์ดํ„ฐ๋ฅผ ์ „์†กํ•˜๋Š” ๊ฒƒ
  • ์ฃผ๋กœ ์ƒํƒœ๊ฐ€ ๋ณ€ํ•˜์ง€ ์•Š๋Š” ๊ฐ’์„ ์ฝ์„ ๋•Œ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค
  • ์ฃผ๋กœ ํ•˜๋‚˜์˜ ์†Œ๋น„์ž(Consumer)์—๊ฒŒ ๊ฐ’์„ ๋ณด๋ƒ…๋‹ˆ๋‹ค.
  • ์ƒ์„ฑ๋œ ์ดํ›„์— ๋ˆ„๊ตฐ๊ฐ€ ์†Œ๋น„ํ•˜๊ธฐ ์‹œ์ž‘ํ•˜๋ฉด ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐœํ–‰ํ•ฉ๋‹ˆ๋‹ค.

๐ŸŽ StateFlow ์‚ฌ์šฉ

๋ฐ์ดํ„ฐ ํ™€๋”(์ €์žฅ์†Œ) ์—ญํ• ์„ ํ•˜๋ฉด์„œ Flow์˜ ๋ฐ์ดํ„ฐ ์ŠคํŠธ๋ฆผ ์—ญํ• ์„ ํ•œ๋‹ค

์ฆ‰, ์—ฌ๋Ÿฌ๊ฐœ์˜ flow์˜ ๋ฐ์ดํ„ฐ ํ™€๋”(์ €์žฅ์†Œ) ์—ญํ• ์„ ํ•˜๋ฉฐ ๋ฐ์ดํ„ฐ ์ŠคํŠธ๋ฆผ์—ญํ• ๊นŒ์ง€ ํ•ฉ๋‹ˆ๋‹ค

๋ฐ‘์— ๊ทธ๋ฆผ์„ ๋ณด๋ฉด

  • ๊ธฐ์กด Flow๋Š” Observer ํ˜•์‹์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ๊ตฌ๋…(emit)ํ•ด์„œ collectํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.
  • ํ•˜์ง€๋งŒ StateFlow๋Š” ์—ฌ๋Ÿฌ๊ฐœ์˜ Flow๊ฐ€ ํ•˜๋‚˜์˜ StateFlow์œผ๋กœ ๋ชจ์—ฌ์ €์„œ ํ•˜๋‚˜์˜ ๊ฐ์ฒด๋กœ ๋งŒ๋“ค์–ด์ง‘๋‹ˆ๋‹ค.

๐Ÿ๋ณ€ํ™˜ ๋ฐฉ๋ฒ•

๐Ÿ“ŒStateIn์„ ์‚ฌ์šฉํ•˜์—ฌ Flow -> StateFlow ๋ณ€ํ™˜ํ•˜๊ธฐ

stateIn์„ ์‚ฌ์šฉํ•ด์„œ ๋ณ€ํ™˜ํ•  ์ˆ˜ ์žˆ๋‹ค.

  • scope : StateFlow๊ฐ€ Flow๋กœ๋ถ€ํ„ฐ ๋ฐ์ดํ„ฐ๋ฅผ ๊ตฌ๋…๋ฐ›์„ CoroutineScope๋ฅผ ๋ช…์‹œํ•œ๋‹ค
  • started: Flow๋กœ๋ถ€ํ„ฐ ์–ธ์ œ๋ถ€ํ„ฐ ๊ตฌ๋…์„ ํ• ์ง€ ๋ช…์‹œํ•  ์ˆ˜ ์žˆ๋‹ค
  • inintalValue: StateFlow์˜ ์ดˆ๊ธฐ๊ฐ’์„ ์„ค์ •ํ•œ๋‹ค.
class MyViewModel(...) : ViewModel() {
    val result: StateFlow<Result<UiState>> = flow {
        emit(repository.fetchItem())
    }.stateIn(
        scope = viewModelScope, 
        started = WhileSubscribed(5000), 
        initialValue = Result.Loading
    )
}

์œ„์— ์ฝ”๋“œ์ค‘ WhileSubscribed(Time)๋Š”๋ญ˜๊นŒ?

๋ฐ‘์— ๊ทธ๋ฆผ์„ ๋ณด๋ฉด ๋‘๊ฐ€์ง€๊ฐ€ ๋‚˜๋ˆ ์ ธ ์žˆ๋‹ค

  • No upstreamFlows cancelled(๊ฐ€๋กœ ํšŒ์ „)
  • All upStreamFlows cancelled After timeout(ํ™ˆ ๋ฒ„ํŠผ)

์‚ฌ์šฉ์ž๊ฐ€ ๋‹ค์‹œ ์•ฑ์„ ์ผฐ์„๋•Œ ๋น ๋ฅด๊ฒŒ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ›์„๋ ค๋ฉด ๋‹ค์‹œ Flow๋ฅผ ์žฌ์‹œ์ž‘ํ•ด์„œ๋Š” ์•ˆ๋œ๋‹ค.

  • ํ™ˆ์œผ๋กœ ๊ฐ”์„๋•Œ๋Š” ๋ฒ ํ„ฐ๋ฆฌ ๋ฐ ๋‹ค๋ฅธ ์ž์›๋ฅผ ์•„๋ผ๊ธฐ ์œ„ํ•ด Flow๋ฅผ ์ค‘๋‹จํ•ด์•ผํ•˜๋ฉฐ
  • ๊ฐ€๋กœ ํšŒ์ „์„ ํ–ˆ์„ ๊ฒฝ์šฐ์—๋Š” ๋น ๋ฅด๊ฒŒ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ›๊ธฐ ์œ„ํ•ด Flow๋ฅผ ์ค‘๋‹จํ•˜๋ฉด ์•ˆ๋œ๋‹ค.

์ด๊ฒƒ์„ ์•Œ๊ธฐ ์œ„ํ•ด์„œ ์‹œ๊ฐ„์ดˆ๊ณผ(WhileSubscribed)๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.

์ด๋ ‡๊ฒŒ ์‹œ๊ฐ„์— ๋”ฐ๋ผ ํ”„๋กœ๊ทธ๋žจ์„ ๋™์ž‘ํ•˜๋Š”๊ฒƒ์„ ์•Œ์•„๋ณด์•˜๋‹ค.

0๊ฐœ์˜ ๋Œ“๊ธ€