Vlad
04/09/2025, 11:31 AMVlad
04/09/2025, 11:32 AMval LocalAppNavigator: ProvidableCompositionLocal<MyNavigator> = staticCompositionLocalOf {
error("")
}
interface MyNavigator {
fun process(request: NavigationRequest)
}
class FeatureA : Screen {
@Composable
override fun Content() {
val appNavigator = LocalAppNavigator.current
FeatureScreen(
onNavigationRequest = {
appNavigator.process(it)
}
)
}
}
@Composable
fun App() {
// Voyager
Navigator(
screen = FeatureA()
) { navigator ->
val appNavigator = remember(navigator) {
object : MyNavigator {
override fun process(request: NavigationRequest) {
navigator.push(
item = when (request) {
is NavigationRequest.ToFeatureX -> FeatureX()
}
)
}
}
}
CompositionLocalProvider(LocalAppNavigator provides appNavigator) {
CurrentScreen()
}
}
}
Stylianos Gakis
04/09/2025, 11:36 AMVlad
04/09/2025, 11:38 AMHow do they expect you to do cross-module navigation there?
That exactly where I am currently stuck lol, trying to modularize my project.
No, it doesn't. It saves fields of the Screen into android bundle, so only those types are allowedStylianos Gakis
04/09/2025, 11:40 AMVlad
04/09/2025, 11:41 AMVlad
04/09/2025, 11:41 AMSergey Y.
04/09/2025, 11:47 AMVlad
04/09/2025, 11:50 AMVlad
04/09/2025, 11:52 AMStylianos Gakis
04/09/2025, 12:01 PMZoltan Demant
04/09/2025, 1:37 PMVlad
04/09/2025, 1:40 PMKamilH
04/10/2025, 6:21 AM@kotlinx.Serializable
or Parcelable
, so none of them allow for direct passing of callbacks.
It is recommended not to overuse CompositionLocals as it introduces hidden dependencies, but if it works for you, then why not
Alternatively, you could do
val appNavigator = FavoriteDiFramework.inject()
or make MyNavigator
a singleton, inject it into the presenters, and proces requests by:
val screen = ...
findNavController().navigateTo(screen)
Stylianos Gakis
04/10/2025, 6:57 AMI would say it's not Voyager's limitation but rather Android's limitation
That would be true if it were not completely trivial to pass callbacks like that in other navigation libraries.
Zoltan Demant
04/10/2025, 7:05 AMKamilH
04/10/2025, 7:19 AMclass ViewModel(navigator: Navigator) {
fun handleSomething() {
navigator.navigateTo(
Screen(id) { result ->
doSomething(result)
}
)
}
}
Zoltan Demant
04/10/2025, 7:21 AMKamilH
04/10/2025, 7:24 AMKamilH
04/10/2025, 7:50 AMScreen
is also Parcelable
, and they have a separate mechanism (similar to rememberLauncherForActivityResult
) to deliver results 🙂Arkadii Ivanov
04/10/2025, 8:17 AM