æã ãKotlin ã«å°å ¥ãããã³ã«ãŒãã³ã¯è»œéã§ããã倿°ã®ã³ã«ãŒãã³ãèµ·åããªãããææã®ã倿Žå¯èœãªç¶æ ã®å ±æãåé¡ãé¿ããªããã³ã«ãŒãã³éã§éä¿¡ããæ¹æ³ãå¿ èŠã§ããã
ããã§ãã³ã«ãŒãã³ééä¿¡ããªããã£ããšã㊠Channel ã远å ãããŸãããChannel ã¯çŽ æŽããããã³ã«ãŒãã³éã®ã1察1ã1察å€ãå€å¯Ÿ1ãå€å¯Ÿå€ã®éä¿¡ããµããŒãã Channel ã«éä¿¡ãããå€ã¯ãã¹ãŠ1åã ãåä¿¡ãããŸãã

Channel ã䜿çšããŠãã€ãã³ããç¶æ ã®æŽæ°ãè€æ°ã®ãµãã¹ã¯ã©ã€ããŒãç¬ç«ããªããåä¿¡ã»åå¿ã§ããããã«é ä¿¡ããããšã¯ã§ããŸããã
ããã㊠BroadcastChannel ãå°å ¥ããããã®å®è£ ãšã㊠buffered ãš ConflatedBroadcastChannel ãå°å ¥ãããŸããããããã¯ããã°ããã®éã¯åœ¹ã«ç«ã£ãŠããŸããããèšèšçã«ã¯è¡ãè©°ã£ãŠããããšãããããŸãããçŸåšãkotlinx-coroutinesããŒãžã§ã³1.4ãããããè¯ã解決çã§ãã SharedFlow ãå°å ¥ããŠããŸãã詳ããã¯ãã®èšäºãã芧ãã ããã
â Flow ã¯ã·ã³ãã«
æå㯠Channel ãããªãã£ãã®ã§ãéåæã·ãŒã±ã³ã¹ã®ããŸããŸãªå€æããã Channel ãåŒæ°ã«ãšããçµæãšããŠå¥ã® Channel ãè¿ã颿°ãšããŠå®è£ ããŠããŸãããããã¯ããã£ã«ã¿ãŒæŒç®åãç¬èªã®ã³ã«ãŒãã³ã§å®è¡ãããããšãæå³ããŸãã

ãã®ãããªæŒç®åã®æ§èœã¯ãif æãæžããå Žåãšæ¯èŒããŠã決ããŠè¯ããšã¯èšããŸããã§ãããåŸããèããŠã¿ããšãããã¯é©ãã¹ãããšã§ã¯ãããŸããããªããªã Channel ã¯åæããªããã£ãã ããã§ããã©ã㪠Channel ã§ããããšããããã¥ãŒãµãŒãšã³ã³ã·ã¥ãŒããŒã1ã€ãã€ã®å Žåã«æé©åãããå®è£ ã§ãã£ãŠããåæã«éä¿¡ããã³ã«ãŒãã³ããµããŒãããå¿ èŠãããããããã®éã®ããŒã¿è»¢éã«ã¯åæãå¿ èŠã§ããéåæããŒã¿ã¹ããªãŒã ã®äžã«ã¢ããªã±ãŒã·ã§ã³ã¢ãŒããã¯ãã£ãæ§ç¯ãå§ãããšãåœç¶ã倿ã®å¿ èŠæ§ãåºãŠã㊠Channel ã®ã³ã¹ããçºçãå§ããŸãã
Kotlin Flow ã®ã·ã³ãã«ãªèšèšã«ããã倿æŒç®åã®å¹ççãªå®è£ ãå¯èœã§ããåºæ¬çãªã±ãŒã¹ã§ã¯ãå€ã® emit ãã collect ãŸã§ãåãã³ã«ãŒãã³å ã§è¡ãããåæã®å¿ èŠã¯ãããŸããã

åæã¯ãç°ãªãã³ã«ãŒãã³ã§ã®å€ã® emit ãš collect ãå¿ èŠãªå Žåã«ã®ã¿ Flow ã䜿ã£ãŠå°å ¥ããŸãã
â Flow ã¯ã³ãŒã«ã
ããã Flow ã¯äžè¬çã«ã³ãŒã«ãã§ã flow { ... } ãã«ããŒé¢æ°ã«ãã£ãŠäœæããã Flow
val coldFlow = flow {
while (isActive) {
emit(nextEvent)
}
}
Flow èªäœã¯ããããªãçš®é¡ã®èšç®ã«ãè£ä»ããããŠããããcollect ãå§ãŸããŸã§ãããèªäœã§ã¯ãããªãç¶æ ãæã¡ãŸããããã¹ãŠã® collect ã³ã«ãŒãã³ã¯ãemit ã³ãŒãã®ç¬èªã®ã€ã³ã¹ã¿ã³ã¹ãå®è¡ããŸãã

ãããããŠãŒã¶ãŒã®ã¢ã¯ã·ã§ã³ãå€éšããã€ã¹ã®ã€ãã³ããç¶æ ã®æŽæ°ãªã©ã¯ã©ã®ããã«åŠçããã®ã§ããããïŒãããã¯ããããã«é¢å¿ãæã€ã³ãŒãããããã©ãããšã¯ç¡é¢ä¿ã«åäœããŸãããããã¯ãã¢ããªã±ãŒã·ã§ã³å ã®è€æ°ã®ãªãã¶ãŒããŒããµããŒãããå¿ èŠããããŸãããããã¯ããããã€ãã³ãã®ããããœãŒã¹ã§ãã
â SharedFlow
ããã§ç»å Žããã®ããSharedFlow ãšããæŠå¿µã§ããSharedFlow ã¯ãcollect ãããŠãããã©ããã«é¢ãããååšã§ããŸããSharedFlow ã® collector ã¯ãµãã¹ã¯ã©ã€ããŒãšåŒã°ããŸããSharedFlow ã®ãã¹ãŠã®ãµãã¹ã¯ã©ã€ããŒã¯ãåãã·ãŒã±ã³ã¹ã®å€ãåãåããŸãããã㯠Channel ã®ãªãŒããŒãããã®ã»ãšãã©ã䌎ããªã BroadcastChannel ã®ããã«å¹æçã«æ©èœããŸããããã«ãããBroadcastChannel ã®æŠå¿µã廿¢ãããŸãã

æ¬è³ªçã« SharedFlow ã¯ã軜éã®ãããŒããã£ã¹ãã€ãã³ããã¹ã§ãã¢ããªã±ãŒã·ã§ã³ã®äžã§äœæããŠäœ¿çšããããšãã§ããŸãã
class BroadcastEventBus {
private val _events = MutableSharedFlow<Event>()
val events = _events.asSharedFlow() // read-only public view
suspend fun postEvent(event: Event) {
_events.emit(event) // suspends until subscribers receive it
}
}
æ°ãããµãã¹ã¯ã©ã€ããŒã®ããã«ä¿æããŠåçããå€ãã€ãã³ãã®æ° replay ããéããšããã¿ãšé ããµãã¹ã¯ã©ã€ããŒã«ã¯ãã·ã§ã³ãæäŸããããã® extraBufferCapacity ãªã©èª¿æŽãã©ã¡ãŒã¿ãæã£ãŠããŸãã
SharedFlow ã®ãã¹ãŠã®ãµãã¹ã¯ã©ã€ããŒã¯ãããããã®ã³ã³ããã¹ãã§ã€ãã³ããéåæçã« collect ããŠããŸãããšããã¿ãŒã¯ããµãã¹ã¯ã©ã€ããŒãã€ãã³ãã®åŠçãçµãããŸã§åŸ ã¡ãŸãããããããSharedFlow ã®ãããã¡ããã£ã±ãã«ãªããšããšããã¿ã¯ãããã¡ã«äœè£ãã§ãããŸã§ãµã¹ãã³ãããŸãããããã¡ãªãŒããããŒæã®ãšããã¿ã®åæ¢ã¯ãã³ã¬ã¯ã¿ãŒã远ãã€ããªããšãã« emit ãé ãããããã®ããã¯ãã¬ãã·ã£ãŒãšãªããŸãããããã¡ãªãŒããããŒã«å¯ŸåŠããå¥ã®æ¹æ³ã¯ãBufferOverlow ãã©ã¡ãŒã¿ã§ãµããŒããããŠããŸãã
â StateFlow
ãããã¡ãªãŒããããŒã«å¯ŸåŠããããã®äžè¬çãªæ¹æ³ã¯ãæãå€ãã€ãã³ããåé€ããæãæ°ããææ°ã®ã€ãã³ãã®ã¿ãä¿æããããšã§ããç¹ã«ãã¢ããªã±ãŒã·ã§ã³ã®ç¶æ 倿°ãã¢ãã«åããã«ã¯æé©ãªæ¹æ³ã§ããããã¯ã廿¢ãããConflatedBroadcastChannel ã®ä»£ãããšãªããå°çšã® StateFlow ã§åºã䜿ãããŠããã±ãŒã¹ã§ãã
class StateModel {
private val _state = MutableStateFlow(initial)
val state = _state.asStateFlow() // read-only public view
fun update(newValue: Value) {
_state.value = newValue // NOT suspending
}
}
val x: StateFlow
StateFlow ã§ã¯ãè€é㪠Channel ãšã·ã³ãã«ãª Flow ã®æ§èœå·®ãã¯ã£ãããšçŸããŸããStateFlow ã®å®è£ ã§ã¯ãã¢ãã±ãŒã·ã§ã³ããªãŒã®æŽæ°ãè¡ãããŸãããããã¯æ··ä¿¡ãã BroadcastChannel ã§ã¯ããã§ã¯ãããŸããã§ããã
â Channel
ããŸããŸãªçš®é¡ã® SharedFlow ãããŸããŸãªçš®é¡ã® BroadcastChannel ã«åã£ãŠä»£ããã«ã€ãã人æ°ã®ãã質åã¯ãæ®éã® Channel ã¯ã©ããªãã®ããšããããšã§ããå€ãã®çç±ãããChannel ã¯åç¶ããã§ãããã1ã€ã®çç±ã¯ãChannel ãå€ãã®è€éFlow æŒç®åãå®è£
ããããã«äœ¿çšãããäœã¬ãã«ã®ããªããã£ãã§ããããšã§ãã
ããããChannel ã«ã¯å¿çšçãªäœ¿çšäŸããããŸããChannel ã¯ãæ£ç¢ºã«äžåºŠã ãåŠçããªããã°ãªããªãã€ãã³ããåŠçããããã«äœ¿çšãããŸã*ïŒè©³çްã¯äžèšã®æ³šéãåç
§ïŒãããã¯ãéåžžã¯1人ã®å å
¥è
ãããããæç¶çã«ïŒèµ·åæãããçš®ã®åæ§ææã«ïŒå å
¥è
ãå
šãããªãã€ãã³ãã¿ã€ãã®ãã¶ã€ã³ã§ãå å
¥è
ãçŸãããŸã§æçš¿ãããã€ãã³ãããã¹ãŠä¿æããªããã°ãªããªããšããèŠä»¶ãããå Žåã«èµ·ãããŸãã
class SingleShotEventBus {
private val _events = Channel<Event>()
val events = _events.receiveAsFlow() // expose as flow
suspend fun postEvent(event: Event) {
_events.send(event) // suspends on buffer overflow
}
}
æåã®äŸã® SharedFlow ã§æžããã BroadcastEventBus ããChannel ã§æžããããã® SingleShotEventBus ããã€ãã³ãã Flow
SharedFlow ã§ã¯ãã€ãã³ãã¯æªç¥æ°ïŒãŒã以äžïŒã®ãµãã¹ã¯ã©ã€ããŒã«ãããŒããã£ã¹ããããŸãããµãã¹ã¯ã©ã€ããŒãããªãå Žåããã¹ããããã€ãã³ãã¯çŽã¡ã«ãããããããŸããããã¯ãããã«åŠçããªããã°ãªããªãã€ãã³ããããŸã£ããåŠçããªãã€ãã³ãã«äœ¿çšãããã¶ã€ã³ãã¿ãŒã³ã§ãã
Channel ã§ã¯ãåã€ãã³ãã1人ã®è³Œèªè ã«é ä¿¡ãããŸãã賌èªè ã®ããªãã€ãã³ããæçš¿ããããšãããšãChannel ã®ãããã¡ããã£ã±ãã«ãªããšããã«äžæããã賌èªè ãçŸããã®ãåŸ ã¡ãŸããæçš¿ãããã€ãã³ãã¯ãããããããŸããã
Channel ãæã€ SingleShotEventBus ã®å®è£ ã§ã¯ããã£ã³ã»ã«ããªãå Žåã«éãããã¹ããããåã€ãã³ããæ£ç¢ºã«1åã ãåŠçããããšã«æ³šæããŠãã ãããFlow ã®ãµãã¹ã¯ã©ã€ããŒããã£ã³ã»ã«ããããšãã€ãã³ãã®é ä¿¡ã«å€±æããããšããããŸãã詳现ã«ã€ããŠã¯ãChannel ã®æªé ä¿¡èŠçŽ ããåç §ããŠãã ããã
â çµè«
SharedFlow ãš Channel ã®éããçè§£ããé©åã«äœ¿ãåããŸããããã©ã¡ãã䟿å©ã§äžç·ã«äœ¿ãããšãåæã«èšèšãããŠããŸãã
ããããBroadcastChannel ã¯éå»ã®éºç©ã§ãããå°æ¥çã«ã¯éæšå¥šãšãªãåé€ãããã§ãããã
👉 StateFlow ã® View ãžã®å
Ž
👉 ãMVVMã Kotlin Flow ã§äœ¿ãã5ã€ã®å©çšãã¿ãŒã³
👉 StateFlow 㯠distinctUtilChanged äžèŠ
é¢é£ã¯ãŒã: Androidã»Kotlinã»ããããã»ä»ããèããªãã»åå¿è ã»éçº