跪拜 Guibai
← All articles
Android · Frontend

Nav3-Router Replaces ARouter with a KSP-Powered, Dual-Track Navigation Framework for Compose

By 达令哥 ·
Read original on juejin.cn ↗ Google Translate ↗ Alt translation

ARouter's reflection and Activity-centric model is a dead end in the single-Activity, Compose-first world. Nav3-Router gives teams a drop-in path to Navigation 3 that doesn't sacrifice the dynamic URL routing and deep-link dispatch product teams rely on, while adding compile-time safety checks that catch duplicate routes before they ship.

Summary

Nav3-Router replaces ARouter's Activity/XML and reflection-based approach with a dual-track routing framework built on Android's Navigation 3 and KSP. It enforces type safety at compile time while still supporting dynamic URL navigation, and it layers on production necessities: automatic navigation-stack restoration after process death, a 404 fallback route to prevent white screens, and a chain-of-responsibility handler for intercepting H5 links or custom schemes. Multi-module setup requires zero Gradle configuration—KSP scans sub-modules and generates unique extension functions on NavCenter.

The framework introduces a decorator onion-skin system via NavEntryDecorator for injecting ViewModel scoping and analytics, alongside a global overlay mechanism that lets any module show a Compose dialog above the current page without pushing a new route. A green-channel option bypasses all interceptors for emergency direct navigation, and a service-discovery system using @Service and IService enables zero-reflection, cross-module calls for UI-less business logic like payment processing.

Shared-element morphing transitions, required-parameter runtime guards, and a pure-Kotlin testable Navigator abstraction round out the offering. The library is published to Maven Central under Apache 2.0.

Takeaways
KSP scans all @Screen annotations at compile time and halts the build if duplicate routes are found, eliminating silent runtime overwrites.
Process-death restoration serializes the entire navigation backstack as a URL list into a Bundle and rebuilds it on relaunch with zero Parcelable risk.
A 404 fallback route (setFallbackRoute) catches malformed or stale deep links and redirects to a safe destination instead of crashing or showing a blank screen.
Multi-module projects need no Gradle configuration; KSP generates a unique NavCenter.initXxx() extension per module based on its package name.
The NavEntryDecorator system wraps pages in an onion-skin pattern, with a built-in decorator that auto-triggers ViewModel onCleared() when a page leaves the stack.
A global overlay API (showOverlay/dismissOverlay) renders any Compose content above the current page without pushing a new route, useful for cross-module cashier dialogs or loading states.
Cross-module service discovery uses @Service and IService with KSP registration, enabling zero-reflection calls to UI-less business logic like payment services.
Green-channel navigation (greenChannel = true) bypasses all global and local interceptors for emergency or privileged direct access to a destination.
Shared-element transitions work through a .sharedElementKey() modifier that binds a key to a composable, enabling cross-page zoom morphing.
The Navigator abstraction allows pure-Kotlin unit testing of navigation logic without an Android or Robolectric environment.
Conclusions

Baking process-death restoration into the router itself, rather than leaving it as an exercise for each team, removes one of the most persistent sources of subtle crashes in Android apps.

The dual-track design—compile-time type safety via KSP for declared screens plus runtime URL strings for dynamic links—acknowledges that real apps need both, and that forcing one model exclusively creates friction.

Generating per-module init functions through KSP instead of requiring manual Gradle wiring sidesteps the configuration drift that plagues large multi-module projects as teams add and remove feature modules.

The overlay system treats dialogs as a first-class navigation concern independent of the backstack, which matches how product flows actually work: a payment sheet shouldn't be a new page in the user's mental model or the system back button's history.

Service discovery with @Service and IService fills a gap that pure navigation frameworks ignore—componentized apps need to call logic across module boundaries without creating compile-time dependency cycles, and doing it through the router's registry avoids yet another DI framework.

Concepts & terms
KSP (Kotlin Symbol Processing)
A Kotlin compiler plugin API that processes annotations at compile time and generates source code, offering a faster, Kotlin-native alternative to kapt (annotation processing). Nav3-Router uses it to scan @Screen annotations, check for duplicate routes, and generate module-specific init functions.
Navigation 3 (androidx.navigation3)
The latest generation of Android's official Navigation component, designed for Jetpack Compose and single-Activity architectures. It introduces NavDisplay for scene rendering and NavEntry for ViewModelStoreOwner management, replacing the older NavHost fragment-based approach.
Process Death Restoration
A mechanism that saves the current navigation stack state into a Bundle when the system kills an app's process in the background, then reconstructs the full page stack when the user returns, so they land exactly where they left off instead of the home screen.
Chain of Responsibility Pattern
A behavioral design pattern where a request passes through a chain of handler objects until one handles it. Nav3-Router uses this for RouteHandler, allowing multiple pre-processors (WebView detection, browser fallback, custom scheme interception) to examine and potentially handle a navigation request before it reaches the router.
NavEntryDecorator
A decorator interface in Nav3-Router that wraps page entries in an onion-skin pattern, allowing cross-cutting concerns like ViewModel scope injection or analytics tracking to be applied uniformly to every page without modifying individual screen composables.
Source: juejin.cn ↗ Google Translate ↗ Backup ↗