Navigator Overview
In compose_bloc the UI is split in Screens and you navigate between the UI Screens with a Navigator. compose_bloc make extensive use of CompositionLocal data so that we can scope data to a specific part of the tree of composable calls that defines the UI. This also allows us to handle the lifecycle of Screens and Navigators that defines the UI of the app.
RootNavigator
We start by defining a RootNavigator
for some Android Activity (or for some Compose Desktop Window):
LocalNavigator
Then in MainScreen
Content()
composable function and all its Composable subtree, we can access the navigator with LocalNavigator.current
or LocalNavigator.currentOrThrow
renderComposableWithNavigator
for Compose Web
renderComposableWithNavigator
for Compose WebFor compose Web instead of RootNavigator
you need to mount the composition at some HTML element using method renderComposableWithNavigator
instead of the usual method renderComposable:
For compose Web in addition to LocalNavigator
also the DOMScope
for the HTML Element to which the navigator was bound, is made available with the CompositionLocal variable LocalDomScope .
Basic Navigator Operations
We can use the navigator instance to push new screens into the stack, or popping the current one if we want to go back to a previous screen.
Navigator and OnBackPressed() events
Navigator has integrated handling of OnBackPressed()
events. In other words when the users navigate away from a screen (pressing the back button on Android), this is handled by calling navigator.pop()
for the local navigator or its parent navigator if the local navigator has no screen that can be popped.
It is also possible to override handling of OnBackPressed()
events by specifying a custom handler in the definition of the navigator. For example, for the RootNavigator
we can write
Nested Navigators
For more complex navigation scenarios, for example for a screen with sub screens with each sub screen with an independent navigation stack, like a screen with tabs, with each tab with an independent navigation stack, we can define nested navigators
Note that usage of RootNavigator
is required only for the top Navigator of the current Activity
Router and path-based navigation.
path-based navigation was not supported in the original voyager library. Its implementation is derived from routing-compose .
Path-based navigation (i.e. navigation to a Screen
with an URL
), is very natural for web apps, but is actually very useful for all platforms, for two main reasons:
support for deep links: for app deep links we need a way to associate a Screen to an URL
decoupling of an app into independent components: for big applications, where multiple features are developed independently in multiple modules, there is usually central module that is the only one linked against all other modules, that implement a router that allows to navigate to Screens of any of the modules without the need of knowing anything of the other modules except the URL of the target screen.
We take a slightly different approach from other navigation libraries like the official Android Compose navigation library, and also routing-compose : In our implementation routing is not part of the composition. It is instead a separate operation that it is executed outside the composition that take as input an URL and return a Screen
that is then pushed into the navigation stack. This way we gain a better separation between UI rendering and routing logic. Let's see an example.
Last updated