はじめに
今回はKotlinを使って単一の発火イベントを流すことができる機構を作っていきます
本文
まず、共通で使えるinterfaceを用意します
今回は単一でハンドリングすることの多いToastにしてみます
sealed interface SideEffect {
data class ShowToast(val message: String) : SideEffect
}
次にToastを使いたいViewModelで下記のように変数を宣言します
// 実態は隠匿しておきたいのでpraivateにしてFlowに変換したものを利用側に流すようにする
private val _sideEffectChannel = Channel<SideEffect>(capacity = Channel.BUFFERED)
val sideEffectFlow: Flow<SideEffect>
get() = _sideEffectChannel.receiveAsFlow()
最後にCompose関数で監視するための関数を用意してあげます
@Composable
fun <T : Any> SingleEffect(
sideEffectFlow: Flow<T>,
lifeCycleState: Lifecycle.State = Lifecycle.State.STARTED,
collector: (T) -> Unit
) {
val lifecycleOwner = LocalLifecycleOwner.current
LaunchedEffect(sideEffectFlow) {
lifecycleOwner.repeatOnLifecycle(lifeCycleState) {
sideEffectFlow.collect(collector)
}
}
}
あとは下記のように使いたい画面でハンドリングをしてあげれば完成です
SingleEffect(viewModel.sideEffectFlow) { sideEffect ->
when (sideEffect) {
is SideEffect.ShowToast -> Toast.makeText(context, sideEffect.message, Toast.LENGTH_SHORT).show()
}
}
最後に
まだ試せてませんがこれをつかえばDeepLink周りなどの単一で発生させたいイベントにも使えるのかなと思います
もし試した方がいらっしゃればコメントに貼っていただけると助かります