Nathaniel Rowe
01/30/2022, 10:32 PMtypealias NavEventListener<T> = (T) -> Unit
class NavEventDispatcher<T> {
var listeners = mutableListOf<NavEventListener<T>>()
fun dispatchEvent(value: T) {
listeners.forEach {
it(value)
}
}
}
@Composable
fun <T> HandleNavEvent(dispatcher: NavEventDispatcher<T>, listener: NavEventListener<T>) {
DisposableEffect(dispatcher) {
dispatcher.listeners.add(listener)
onDispose {
dispatcher.listeners.clear()
}
}
}
Basically, a screen composable calls HandleNavEvent(viewModel.dispatcher) { eventPayload -> onNavigate(...) }
, and the view model simply adds a dispatcher instance. I have this dispatcher as a second public property of the view model alongside a single state flow describing the UI state. My question is, is there a better way to do this? It seems to work for the most part, I'm new to compose and am wondering if there is anything I'm not considering here.
The motivation for this is my architecture has it such that, if we just navigate by watching the UI state, then when we navigate back, you bounce right back to the second screen because the UI state for the previous screen is still one which means "navigate forward". I needed a way to reset the state, and didn't want to have a requirement that all my UI states have a "reset" method which resets only part of it. I figured separating the UI state from the navigation state was the way to go.heckfyxe
01/31/2022, 1:21 AMprivate val _captureEvents = Channel<Unit>()
val captureEvents = _captureEvents.receiveAsFlow()
And collect flow in compose function
LaunchedEffect(true) {
viewModel.captureEvents.collect {
showSnackbar(it)
}
}
Nathaniel Rowe
01/31/2022, 3:07 AMNathaniel Rowe
01/31/2022, 3:25 AMheckfyxe
01/31/2022, 4:16 AMheckfyxe
01/31/2022, 4:21 AM