Вы можете использовать встроенные в типобезопасных API, чтобы обеспечить безопасность типов во время компиляции вашего навигационного графа. Эти API доступны, если ваше приложение использует Navigation Compose или Navigation Kotlin DSL. Они доступны начиная с версии Navigation 2.8.0.
У меня есть:
libs.versions .toml
Код: Выделить всё
[versions]
.
.
.
composeNavigation = "2.8.0-beta02"
serialization = "1.6.3"
org-jetbrains-kotlin-jvm = "2.0.0"
[libraries]
.
.
.
navigation-compose = { module = "androidx.navigation:navigation-compose", version.ref = "composeNavigation" }
kotlinx-serialization-json = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref = "serialization"}
[plugins]
.
.
.
kotlin-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" }
org-jetbrains-kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "org-jetbrains-kotlin-jvm" }
Код: Выделить всё
// Top-level build file where you can add configuration options common to all sub-projects/modules.
@Suppress("DSL_SCOPE_VIOLATION") // TODO: Remove once KTIJ-19369 is fixed
plugins {
alias(libs.plugins.android.application) apply false
alias(libs.plugins.jetbrains.kotlin.android) apply false
alias(libs.plugins.compose.compiler) apply false
alias(libs.plugins.com.google.dagger.hilt.android) apply false
alias(libs.plugins.com.google.devtools.ksp) apply false
alias(libs.plugins.androidx.room) apply false
alias(libs.plugins.org.jetbrains.kotlin.jvm) apply false
}
Код: Выделить всё
@Suppress("DSL_SCOPE_VIOLATION") // TODO: Remove once KTIJ-19369 is fixed
plugins {
alias(libs.plugins.android.application)
alias(libs.plugins.jetbrains.kotlin.android)
alias(libs.plugins.com.google.devtools.ksp)
alias(libs.plugins.com.google.dagger.hilt.android)
alias(libs.plugins.kotlin.serialization)
// Existing plugins
alias(libs.plugins.compose.compiler)
alias(libs.plugins.androidx.room)
}
android {
namespace = "com.being.coder.app.newtodo"
compileSdk = 34
defaultConfig {
applicationId = "com.being.coder.app.newtodo"
minSdk = 24
targetSdk = 34
versionCode = 1
versionName = "1.0"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
vectorDrawables {
useSupportLibrary = true
}
}
buildTypes {
release {
isMinifyEnabled = false
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
)
}
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
kotlinOptions {
jvmTarget = JavaVersion.VERSION_17.toString()
}
kotlin {
sourceSets.all {
languageSettings.enableLanguageFeature("ExplicitBackingFields")
}
}
buildFeatures {
compose = true
}
packaging {
resources {
excludes += "/META-INF/{AL2.0,LGPL2.1}"
}
}
room {
schemaDirectory("$projectDir/schemas")
}
}
dependencies {
// Other dependencies
implementation(libs.navigation.compose)
implementation(libs.kotlinx.serialization.json)
}
Код: Выделить всё
@Composable
fun SetupNavigation(
navController: NavHostController
) {
val screens = remember(navController) {
Screens(navController = navController)
}
NavHost(
navController = navController,
startDestination = Home
) {
addHomeScreen(
navigateToTaskScreen = screens.detail
)
}
}
@Serializable
data class Home(
val action: String
)
@Serializable
data class Details(
val id: Int
)
fun NavGraphBuilder.addHomeScreen(
navigateToTaskScreen: (Int) -> Unit
){
composable{
HomeScreen(navigateToTaskScreen = navigateToTaskScreen)
}
}
class Screens(
navController: NavHostController
) {
val home: (Action) -> Unit = {
navController.navigate(Home(it.name)) {
popUpTo(Home) { inclusive = true }
}
}
val detail: (Int) -> Unit = {
navController.navigate(Details(it))
}
}
Код: Выделить всё
@AndroidEntryPoint
class MainActivity : ComponentActivity() {
private lateinit var navController: NavHostController
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
setContent {
NewTodoTheme {
navController = rememberNavController()
SetupNavigation(
navController = navController
)
}
}
}
}
Код: Выделить всё
2024-06-02 23:00:10.811 25777-25777 AndroidRuntime com.being.coder.app.newtodo E FATAL EXCEPTION: main (Ask Gemini)
Process: com.being.coder.app.newtodo, PID: 25777
kotlinx.serialization.SerializationException: S e r i a l i z e r f o r c l a s s ' C o m p a n i o n ' i s n o t f o u n d . < b r / > P l e a s e e n s u r e t h a t c l a s s i s m a r k e d a s ' @ S e r i a l i z a b l e ' a n d t h a t t h e s e r i a l i z a t i o n c o m p i l e r p l u g i n i s a p p l i e d . < b r / > < b r / > a t k o t l i n x . s e r i a l i z a t i o n . i n t e r n a l . P l a t f o r m _ c o m m o n K t . s e r i a l i z e r N o t R e g i s t e r e d ( P l a t f o r m . c o m m o n . k t : 9 0 ) < b r / > a t k o t l i n x . s e r i a l i z a t i o n . S e r i a l i z e r s K t _ _ S e r i a l i z e r s K t . s e r i a l i z e r ( S e r i a l i z e r s . k t : 2 9 9 ) < b r / > a t k o t l i n x . s e r i a l i z a t i o n . S e r i a l i z e r s K t . s e r i a l i z e r ( U n k n o w n S o u r c e : 1 ) < b r / > a t a n d r o i d x . n a v i g a t i o n . N a v G r a p h . s e t S t a r t D e s t i n a t i o n ( N a v G r a p h . k t : 4 0 3 ) < b r / > a t a n d r o i d x . n a v i g a t i o n . N a v G r a p h B u i l d e r . b u i l d ( N a v G r a p h B u i l d e r . k t : 3 2 1 ) < b r / > a t a n d r o i d x . n a v i g a t i o n . c o m p o s e . N a v H o s t K t . N a v H o s t ( N a v H o s t . k t : 7 1 6 ) < b r / > a t c o m . b e i n g . c o d e r . a p p . n e w t o d o . n a v . S e t u p N a v i g a t i o n K t . S e t u p N a v i g a t i o n ( S e t u p N a v i g a t i o n . k t : 1 9 ) < b r / > a t c o m . b e i n g . c o d e r . a p p . n e w t o d o . M a i n A c t i v i t y $ o n C r e a t e $ 1 $ 1 . i n v o k e ( M a i n A c t i v i t y . k t : 2 4 ) < b r / > a t c o m . b e i n g . c o d e r . a p p . n e w t o d o . M a i n A c t i v i t y $ o n C r e a t e $ 1 $ 1 . i n v o k e ( M a i n A c t i v i t y . k t : 2 2 ) < b r / > a t a n d r o i d x . c o m p o s e . r u n t i m e . i n t e r n a l . C o m p o s a b l e L a m b d a I m p l . i n v o k e ( C o m p o s a b l e L a m b d a . j v m . k t : 1 0 9 ) < b r / > a t a n d r o i d x . c o m p o s e . r u n t i m e . i n t e r n a l . C o m p o s a b l e L a m b d a I m p l . i n v o k e ( C o m p o s a b l e L a m b d a . j v m . k t : 3 5 ) < b r / > a t a n d r o i d x . c o m p o s e . r u n t i m e . C o m p o s i t i o n L o c a l K t . C o m p o s i t i o n L o c a l P r o v i d e r ( C o m p o s i t i o n L o c a l . k t : 4 0 1 ) < b r / > a t a n d r o i d x . c o m p o s e . m a t e r i a l 3 . T e x t K t . P r o v i d e T e x t S t y l e ( T e x t . k t : 3 5 2 ) < b r / > a t a n d r o i d x . c o m p o s e . m a t e r i a l 3 . M a t e r i a l T h e m e K t $ M a t e r i a l T h e m e $ 1 . i n v o k e ( M a t e r i a l T h e m e . k t : 7 2 ) < b r / > a t a n d r o i d x . c o m p o s e . m a t e r i a l 3 . M a t e r i a l T h e m e K t $ M a t e r i a l T h e m e $ 1 . i n v o k e ( M a t e r i a l T h e m e . k t : 7 1 ) < b r / > a t a n d r o i d x . c o m p o s e . r u n t i m e . i n t e r n a l . C o m p o s a b l e L a m b d a I m p l . i n v o k e ( C o m p o s a b l e L a m b d a . j v m . k t : 1 0 9 ) < b r / > at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:35)
at androidx.compose.runtime.CompositionLocalKt.CompositionLocalProvider(CompositionLocal.kt:380)
at androidx.compose.material3.MaterialThemeKt.MaterialTheme(MaterialTheme.kt:64)
at com.being.coder.app.newtodo.ui.theme.ThemeKt.NewTodoTheme(Theme.kt:53)
at com.being.coder.app.newtodo.MainActivity$onCreate$1.invoke(MainActivity.kt:22)
at com.being.coder.app.newtodo.MainActivity$onCreate$1.invoke(MainActivity.kt:21)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:109)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:35)
at androidx.compose.ui.platform.ComposeView.Content(ComposeView.android.kt:441)
at androidx.compose.ui.platform.AbstractComposeView$ensureCompositionCreated$1.invoke(ComposeView.android.kt:259)
at androidx.compose.ui.platform.AbstractComposeView$ensureCompositionCreated$1.invoke(ComposeView.android.kt:258)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:109)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:35)
at androidx.compose.runtime.CompositionLocalKt.CompositionLocalProvider(CompositionLocal.kt:380)
at androidx.compose.ui.platform.CompositionLocalsKt.ProvideCommonCompositionLocals(CompositionLocals.kt:216)
at androidx.compose.ui.platform.AndroidCompositionLocals_androidKt$ProvideAndroidCompositionLocals$3.invoke(AndroidCompositionLocals.android.kt:132)
at androidx.compose.ui.platform.AndroidCompositionLocals_androidKt$ProvideAndroidCompositionLocals$3.invoke(AndroidCompositionLocals.android.kt:131)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:109)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:35)
at androidx.compose.runtime.CompositionLocalKt.CompositionLocalProvider(CompositionLocal.kt:380)
at androidx.compose.ui.platform.AndroidCompositionLocals_androidKt.ProvideAndroidCompositionLocals(AndroidCompositionLocals.android.kt:121)
at androidx.compose.ui.platform.WrappedComposition$setContent$1$1$3.invoke(Wrapper.android.kt:155)
at androidx.compose.ui.platform.WrappedComposition$setContent$1$1$3.invoke(Wrapper.android.kt:154)
2024-06-02 23:00:10.815 25777-25777 AndroidRuntime com.being.coder.app.newtodo E at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:109) ( A s k G e m i n i ) < b r / > a t a n d r o i d x . c o m p o s e . r u n t i m e . i n t e r n a l . C o m p o s a b l e L a m b d a I m p l . i n v o k e ( C o m p o s a b l e L a m b d a . j v m . k t : 3 5 ) < b r / > a t a n d r o i d x . c o m p o s e . r u n t i m e . C o m p o s i t i o n L o c a l K t . C o m p o s i t i o n L o c a l P r o v i d e r ( C o m p o s i t i o n L o c a l . k t : 4 0 1 ) < b r / > a t a n d r o i d x . c o m p o s e . u i . p l a t f o r m . W r a p p e d C o m p o s i t i o n $ s e t C o n t e n t $ 1 $ 1 . i n v o k e ( W r a p p e r . a n d r o i d . k t : 1 5 4 ) < b r / > a t a n d r o i d x . c o m p o s e . u i . p l a t f o r m . W r a p p e d C o m p o s i t i o n $ s e t C o n t e n t $ 1 $ 1 . i n v o k e ( W r a p p e r . a n d r o i d . k t : 1 3 3 ) < b r / > a t a n d r o i d x . c o m p o s e . r u n t i m e . i n t e r n a l . C o m p o s a b l e L a m b d a I m p l . i n v o k e ( C o m p o s a b l e L a m b d a . j v m . k t : 1 0 9 ) < b r / > a t a n d r o i d x . c o m p o s e . r u n t i m e . i n t e r n a l . C o m p o s a b l e L a m b d a I m p l . i n v o k e ( C o m p o s a b l e L a m b d a . j v m . k t : 3 5 ) < b r / > a t a n d r o i d x . c o m p o s e . r u n t i m e . A c t u a l J v m _ j v m K t . i n v o k e C o m p o s a b l e ( A c t u a l J v m . j v m . k t : 9 7 ) < b r / > a t a n d r o i d x . c o m p o s e . r u n t i m e . C o m p o s e r I m p l . d o C o m p o s e ( C o m p o s e r . k t : 3 5 9 3 ) < b r / > a t a n d r o i d x . c o m p o s e . r u n t i m e . C o m p o s e r I m p l . c o m p o s e C o n t e n t $ r u n t i m e _ r e l e a s e ( C o m p o s e r . k t : 3 5 2 0 ) < b r / > a t a n d r o i d x . c o m p o s e . r u n t i m e . C o m p o s i t i o n I m p l . c o m p o s e C o n t e n t ( C o m p o s i t i o n . k t : 7 4 3 ) < b r / > a t a n d r o i d x . c o m p o s e . r u n t i m e . R e c o m p o s e r . c o m p o s e I n i t i a l $ r u n t i m e _ r e l e a s e ( R e c o m p o s e r . k t : 1 1 1 4 ) < b r / > a t a n d r o i d x . c o m p o s e . r u n t i m e . C o m p o s i t i o n I m p l . c o m p o s e I n i t i a l ( C o m p o s i t i o n . k t : 6 4 9 ) < b r / > a t a n d r o i d x . c o m p o s e . r u n t i m e . C o m p o s i t i o n I m p l . s e t C o n t e n t ( C o m p o s i t i o n . k t : 6 3 5 ) < b r / > a t a n d r o i d x . c o m p o s e . u i . p l a t f o r m . W r a p p e d C o m p o s i t i o n $ s e t C o n t e n t $ 1 . i n v o k e ( W r a p p e r . a n d r o i d . k t : 1 3 3 ) < b r / > a t a n d r o i d x . c o m p o s e . u i . p l a t f o r m . W r a p p e d C o m p o s i t i o n $ s e t C o n t e n t $ 1 . i n v o k e ( W r a p p e r . a n d r o i d . k t : 1 2 4 ) < b r / > a t a n d r o i d x . c o m p o s e . u i . p l a t f o r m . A n d r o i d C o m p o s e V i e w . s e t O n V i e w T r e e O w n e r s A v a i l a b l e ( A n d r o i d C o m p o s e V i e w . a n d r o i d . k t : 1 5 9 7 ) < b r / > a t a n d r o i d x . c o m p o s e . u i . p l a t f o r m .WrappedComposition.setContent(Wrapper.android.kt:124)
at androidx.compose.ui.platform.WrappedComposition.onStateChanged(Wrapper.android.kt:180)
at androidx.lifecycle.LifecycleRegistry$ObserverWithState.dispatchEvent(LifecycleRegistry.jvm.kt:320)
at androidx.lifecycle.LifecycleRegistry.addObserver(LifecycleRegistry.jvm.kt:198)
at androidx.compose.ui.platform.WrappedComposition$setContent$1.invoke(Wrapper.android.kt:131)
at androidx.compose.ui.platform.WrappedComposition$setContent$1.invoke(Wrapper.android.kt:124)
at androidx.compose.ui.platform.AndroidComposeView.onAttachedToWindow(AndroidComposeView.android.kt:1678)
at android.view.View.dispatchAttachedToWindow(View.java:20820)
at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3550)
at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3557)
at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3557)
at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3557)
at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3557)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2730)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:2234)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:9027)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1105)
at android.view.Choreographer.doCallbacks(Choreographer.java:896)
at android.view.Choreographer.doFrame(Choreographer.java:815)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:1090)
at android.os.Handler.handleCallback(Handler.java:938)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loopOnce(Looper.java:201)
at android.os.Looper.loop(Looper.java:288)
at android.app.ActivityThread.main(ActivityThread.java:7886)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:568)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1045)
Подробнее здесь: https://stackoverflow.com/questions/785 ... ion-is-not
Мобильная версия