I’ve just completed the migration from navigation to Navigation 3, and successfully maintained consistent behavior across the app. Here’s my summary of the experience:
Pros:
- Custom navigation stack management
Unlike the previous navigation API, Navigation 3 allows me to manage the navigation stack myself, which gives much more flexibility. It becomes easier to handle complex navigation scenarios—for example, implementing bottom navigation with individual stacks can be done cleanly using TopLevelBackStack from the nav3recipes sample.
- Elegant SceneStrategy design
Compared to the old approach of creating custom navigators, SceneStrategy feels more extensible and maintainable. It also better accommodates different navigation patterns—for instance, a list-detail UI can now be implemented directly with SceneStrategy, without needing something like NavigableListDetailPaneScaffold.
- Fewer NavHost layers and more consistent navigation
With the previous navigation, implementing bottom navigation with individual stacks often required nesting NavHosts. Combine that with NavigableListDetailPaneScaffold and you could end up with multiple levels of nesting, making things difficult to manage. After migrating to Navigation 3, I now only use a single NavDisplay across the app. Since I manage the navigation stack manually, I can navigate directly without needing additional NavHost layers.
Cons:
- Migration cost
Moving to Navigation 3 takes time and effort, especially for large applications.
- Bottom navigation requires extra care
By default, switching bottom navigation tabs clears the SavedState and ViewModelStore, which breaks expected behavior. To fix this, I wrote custom decorators:
rememberSavedStateNavEntryDecorator2 and
rememberViewModelStoreNavEntryDecorator2.
- Manual deeplink handling
Deeplinks currently aren’t built-in. Unfortunately, my app relies heavily on deeplink-based navigation, so I had to implement my own parsing and navigation logic. Hopefully, native deeplink support will come to Navigation 3 in the future.
If you’re interested in the implementation details, here’s the migration PR:
https://github.com/DimensionDev/Flare/pull/965