mirror of
https://github.com/meshtastic/Meshtastic-Android.git
synced 2026-06-01 22:19:18 +02:00
f4b6b02ace
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
4.7 KiB
4.7 KiB
Skill: DI and Navigation 3 Architecture
Description
This skill covers dependency injection (Koin Annotations 4.2.x) and JetBrains Navigation 3 (1.1.x) architecture, constraints, and anti-patterns within the Meshtastic-Android KMP codebase.
Dependency Injection (Koin)
Guidelines
- Annotations First: Use
@Module,@ComponentScan, and@KoinViewModelannotations directly incommonMainshared modules to encapsulate dependency graphs per feature. - App Root Assembly: Don't assume feature/core
@Moduleclasses are active automatically. Ensure they are included by the app root module (@Module(includes = [...])) inandroidApp/src/main/kotlin/org/meshtastic/app/di/AppKoinModule.ktanddesktopApp/.../DesktopKoinModule.kt. - No Platform Bleed: Don't put Android framework dependencies (
Context,Activity,Application) into sharedcommonMainbusiness logic. Inject interfaces instead. - Resolution: Resolve app-layer wrappers via
koinViewModel()or injected bindings within Compose navigation graphs.
Anti-Patterns
- A1 Module Compile Safety: Do not enable
compileSafety. It is a single boolean that enables A1 per-module checks — there is no separate A3 full-graph mode. Runtime graph verification is handled byKoinVerificationTestandDesktopKoinTestinstead. - Default Parameters: Do not expect Koin to inject default parameters automatically. The K2 plugin's
skipDefaultValues = truebehavior skips parameters with default Kotlin values.
Koin Startup Pattern (K2 Compiler Plugin)
The project uses the K2 Compiler Plugin (koin-compiler-plugin, not KSP). The canonical startup uses the plugin's typed startKoin<T>() stub, which the plugin transforms at compile time via IR:
// Bootstrap class — separate from @Module, references the root module graph
@KoinApplication(modules = [AppKoinModule::class])
object AndroidKoinApp
// In Application.onCreate()
startKoin<AndroidKoinApp> {
androidContext(this@MeshUtilApplication)
workManagerFactory()
}
@KoinApplicationgoes on a dedicated bootstrap object, not on a@Moduleclass.startKoin<T>()(fromorg.koin.plugin.module.dsl) is a compiler plugin stub — if the plugin isn't applied, it throwsNotImplementedError.stopKoin()uses the standard runtime API (org.koin.core.context.stopKoin).compileSafetymust stay disabled — it enables A1 per-module checks that break our inverted-dependency architecture. There is no separate A3 full-graph flag.
Navigation 3
Guidelines
- Types: Use Navigation 3 types consistently (
NavKey,NavBackStack,EntryProviderScope). - Typed Routes: Keep route definitions in
core:navigation/src/commonMain/.../Routes.ktas@Serializable sealed interfacehierarchies. Don't use ad-hoc strings. - Graph Assembly: Define feature navigation graphs as extension functions on
EntryProviderScope<NavKey>incommonMain(e.g.,fun EntryProviderScope<NavKey>.settingsGraph(backStack)). - Host Integration: Use
MeshtasticNavDisplay(fromcore:ui/commonMain) as the Navigation 3 host. Do not configure decorators manually inside feature modules. - Back Handlers: Use
NavigationBackHandlerfromandroidx.navigationevent:navigationevent-composefor back gestures in multiplatform code. Do not use Android'sBackHandler. - Deep Links: Use
DeepLinkRouter.route()incore:navigationto synthesize typed backstacks from RESTful paths.
Anti-Patterns
- Single Backstack for Multiple Tabs: Do not use a single
NavBackStacklist for multiple tabs. UseMultiBackstack(fromcore:navigation). - Decorator Reuse Across Tabs: Do not reuse the same
NavEntryDecoratorinstances across different backstacks. When rendering an active tab inMeshtasticNavDisplay, you must supply a fresh set of decorators (usingremember(backStack) { ... }) bound to the active backstack instance to prevent permanentViewModelStoredestruction. - Custom Backstack Mutation: Do not mutate back navigation with custom stacks disconnected from the app backstack. Mutate
NavBackStack<NavKey>directly withadd(...)andremoveLastOrNull().
Reference Anchors
- App Startup / Koin Bootstrap:
androidApp/src/main/kotlin/org/meshtastic/app/MeshUtilApplication.kt - DI Bootstrap Object:
androidApp/src/main/kotlin/org/meshtastic/app/di/AndroidKoinApp.kt - DI App Wiring:
androidApp/src/main/kotlin/org/meshtastic/app/di/AppKoinModule.kt - Shared Routes:
core/navigation/src/commonMain/kotlin/org/meshtastic/core/navigation/Routes.kt - Desktop Nav Shell:
desktopApp/src/main/kotlin/org/meshtastic/desktop/ui/DesktopMainScreen.kt