spierce7
12/02/2023, 7:34 PMComposable
, but I'm doing all my business logic in the ViewModel
. I'm curious, what do people do to drive screen changes from the ViewModel
, or is even the goal of doing this wrong?Zach Klippenstein (he/him) [MOD]
12/03/2023, 2:41 AMspierce7
12/03/2023, 2:46 AMefemoney
12/04/2023, 10:26 AM// marker interface
// eg subclasses could be DeepLink(uri), PopBackStack, Route(string)
interface Direction or Command
interface Navigator {
fun navigate(direction: Direction)
}
For the implementation pass those navigation commands into a channel. I chose a plain channel cos it models navigation events better (emissions are handled once)
internal class RealNavigator : Navigator {
val channel = Channel<Direction>()
override fun navigate(direction: Direction) {
channel.trySend(direction)
}
}
In your activity or root of your nav graph, collect these āeventsā and handle them
@Composable
internal fun CollectFromNavigator(
navController: NavController,
navigator: RealNavigator,
) {
LaunchedEffect(navController, navigator) {
navigator.channel.receiveAsFlow().collect(navController::handle)
}
}
You can now inject a Navigator into your VM|Presenter and call navigate from business layerStylianos Gakis
12/04/2023, 4:49 PMA > B
to A
(by popping backstack), you might also then consume an event to go to C
and end up with A > C
even though you might have wanted to cancel the move to C
if you are already popping.
This entire thing can get tricky, and while I totally see navigation as business logic too, Iāve had much better luck just modeling such situations as state, and handling them by reporting back to the VM that this ānav eventā is handled and navigating, as opposed to āfire and forgetā navigation events.spierce7
12/04/2023, 4:52 PMIāve had much better luck just modeling such situations as stateThis is how I've handled things with decompose, but I've found it to be extremely verbose.
efemoney
12/04/2023, 4:52 PMStylianos Gakis
12/04/2023, 4:53 PMStylianos Gakis
12/04/2023, 4:53 PMThis is how Iāve handled things with decompose, but Iāve found it to be extremely verbose.Verbose is one way to put it. Reliable is another way to put it š
efemoney
12/04/2023, 4:53 PMIāve had much better luck just modeling such situations as stateI would say avoid this at all if possible. Nav events are not āstateā.
efemoney
12/04/2023, 4:55 PMC
and end up with A > C
even though you might have wanted to cancel the move to C
if you are already popping.
This is not a problem of this approach š¤ , in fact it has nothing to do with this and everything to do with nav library if this is allowed. Channels are internally synchronized afaikStylianos Gakis
12/04/2023, 4:57 PMA
, it then also navigates to C
⢠Youāre now at A > C
efemoney
12/04/2023, 5:00 PMStylianos Gakis
12/04/2023, 5:02 PMNot buffering nav events (or buffering in certain situations eg on rotation)
?efemoney
12/04/2023, 5:18 PMA
, so yeah that wont really work.Stylianos Gakis
12/04/2023, 5:24 PM