Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Can't start app only with Navigation <= No interface method startRestartGroup on ChildrenKt.Children(Children.kt:22) #122

Closed
liplum opened this issue Jun 16, 2022 · 7 comments

Comments

@liplum
Copy link

liplum commented Jun 16, 2022

I followed this tutorial.
Of course, I checked this on medium.com

I almost only copied codes from the tutorial and changed the package name.

When starting desktop on InteliiJ IDEA:

Exception in thread "main" java.lang.NoSuchMethodError: androidx.compose.runtime.Composer.startRestartGroup(ILjava/lang/String;)Landroidx/compose/runtime/Composer;
	at com.arkivanov.decompose.extensions.compose.jetbrains.ChildrenKt.Children(Children.kt:22)
	at net.liplum.common.ScreenKt.Root(Screen.kt:90)
	at net.liplum.common.ComposableSingletons$AppKt$lambda-1$1.invoke(App.kt:10)
	at net.liplum.common.ComposableSingletons$AppKt$lambda-1$1.invoke(App.kt:9)
	at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:107)
	at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:34)
	at androidx.compose.runtime.CompositionLocalKt.CompositionLocalProvider(CompositionLocal.kt:228)
	at androidx.compose.material.MaterialTheme_desktopKt.PlatformMaterialTheme(MaterialTheme.desktop.kt:26)
	at androidx.compose.material.MaterialThemeKt$MaterialTheme$1$1.invoke(MaterialTheme.kt:82)
	at androidx.compose.material.MaterialThemeKt$MaterialTheme$1$1.invoke(MaterialTheme.kt:81)
	at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:107)
	at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:34)
	at androidx.compose.runtime.CompositionLocalKt.CompositionLocalProvider(CompositionLocal.kt:228)
	at androidx.compose.material.TextKt.ProvideTextStyle(Text.kt:265)
	at androidx.compose.material.MaterialThemeKt$MaterialTheme$1.invoke(MaterialTheme.kt:81)
	at androidx.compose.material.MaterialThemeKt$MaterialTheme$1.invoke(MaterialTheme.kt:80)
	at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:107)
	at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:34)
	at androidx.compose.runtime.CompositionLocalKt.CompositionLocalProvider(CompositionLocal.kt:228)
	at androidx.compose.material.MaterialThemeKt.MaterialTheme(MaterialTheme.kt:72)
	at net.liplum.common.AppKt.App(App.kt:9)
	at net.liplum.desktop.ComposableSingletons$MainKt$lambda-1$1.invoke(Main.kt:8)
	at net.liplum.desktop.ComposableSingletons$MainKt$lambda-1$1.invoke(Main.kt:7)

When starting android on Android Studio.

E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.myapplication, PID: 24932
    java.lang.NoSuchMethodError: No interface method startRestartGroup(ILjava/lang/String;)Landroidx/compose/runtime/Composer; in class Landroidx/compose/runtime/Composer; or its super classes (declaration of 'androidx.compose.runtime.Composer' appears in /data/app/~~cveqtxczmcjgqqWLQeHzrA==/com.myapplication-ztE8pb2vmNxy0BTJ1BWwxg==/base.apk)
        at com.arkivanov.decompose.extensions.compose.jetbrains.ChildrenKt.Children(Children.kt:22)
        at net.liplum.common.ScreenKt.Root(Screen.kt:90)
        at net.liplum.common.ComposableSingletons$AppKt$lambda-1$1.invoke(App.kt:10)
        at net.liplum.common.ComposableSingletons$AppKt$lambda-1$1.invoke(App.kt:9)
        at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:107)
        at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:34)
        at androidx.compose.material.MaterialTheme_androidKt.PlatformMaterialTheme(MaterialTheme.android.kt:23)
        at androidx.compose.material.MaterialThemeKt$MaterialTheme$1$1.invoke(MaterialTheme.kt:82)
        at androidx.compose.material.MaterialThemeKt$MaterialTheme$1$1.invoke(MaterialTheme.kt:81)
        at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:107)
        at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:34)
        at androidx.compose.runtime.CompositionLocalKt.CompositionLocalProvider(CompositionLocal.kt:228)
        at androidx.compose.material.TextKt.ProvideTextStyle(Text.kt:265)
        at androidx.compose.material.MaterialThemeKt$MaterialTheme$1.invoke(MaterialTheme.kt:81)
        at androidx.compose.material.MaterialThemeKt$MaterialTheme$1.invoke(MaterialTheme.kt:80)
        at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:107)
        at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:34)
        at androidx.compose.runtime.CompositionLocalKt.CompositionLocalProvider(CompositionLocal.kt:228)
        at androidx.compose.material.MaterialThemeKt.MaterialTheme(MaterialTheme.kt:72)
        at net.liplum.common.AppKt.App(App.kt:9)
        at net.liplum.android.ComposableSingletons$MainActivityKt$lambda-1$1.invoke(MainActivity.kt:13)
        at net.liplum.android.ComposableSingletons$MainActivityKt$lambda-1$1.invoke(MainActivity.kt:12)
@arkivanov
Copy link
Owner

This looks like a binary compatibility issue. What Compose version are you using?

@liplum
Copy link
Author

liplum commented Jun 16, 2022

// gradle.properties
org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
android.useAndroidX=true
android.enableJetifier=true
kotlin.code.style=official
kotlin.version=1.6.10
agp.version=7.0.4
compose.version=1.1.0
// desktop/build.gradle.kts
kotlinOptions.jvmTarget = "11"
// common/build.gradle.kts
import org.jetbrains.compose.compose

plugins {
    id("com.android.library")
    kotlin("multiplatform")
    id("org.jetbrains.compose")
    id("kotlin-parcelize")
}
kotlin {
    android()
    jvm("desktop")

    sourceSets {
        named("commonMain") {
            dependencies {
                api(compose.runtime)
                api(compose.foundation)
                api(compose.material)
                // Needed only for preview.
                implementation(compose.preview)
                api("com.arkivanov.decompose:decompose:0.2.3")
                api("com.arkivanov.decompose:extensions-compose-jetbrains:0.2.3")
            }
        }
        named("androidMain") {
            dependencies {
                api("androidx.appcompat:appcompat:1.3.1")
                api("androidx.core:core-ktx:1.6.0")
            }
        }
    }
}
android {
    compileSdkVersion(31)

    defaultConfig {
        minSdkVersion(21)
        targetSdkVersion(31)
    }

    compileOptions {
        sourceCompatibility = JavaVersion.VERSION_11
        targetCompatibility = JavaVersion.VERSION_11
    }

    sourceSets {
        named("main") {
            manifest.srcFile("src/androidMain/AndroidManifest.xml")
            res.srcDirs("src/androidMain/res")
        }
    }
}
// IDE
Android Studio 2021.2.1 Patch 1
gradle-7.3.3

@arkivanov
Copy link
Owner

Aha! You are using a very old version of Decompose. Try updating to the latest one - 0.6.0. It should be compatible with Compose 1.1.0.

@arkivanov
Copy link
Owner

You may encounter source incompatibility, feel free to ask if something doesn't compile and you are unsure how to migrate.

@liplum
Copy link
Author

liplum commented Jun 16, 2022

Thanks, I switched to 0.6.0 just now.

The migration is easy, just replacing something with essenty in IDEA, except ComponentContext.router.

There is no clue for this one:

@Composable
fun <C : Parcelable> rememberRouter(
    initialConfiguration: () -> C,
    initialBackStack: () -> List<C> = ::emptyList,
    configurationClass: KClass<out C>,
    handleBackButton: Boolean = false,
): Router<C, Any> {
    val context = rememberComponentContext()

    return remember {
        context.router(
            initialConfiguration = initialConfiguration,
            initialBackStack = initialBackStack,
            configurationClass = configurationClass,
            handleBackButton = handleBackButton
        ) { configuration, _ ->
            configuration
        }
    }
}

Of course, you know, Please use ComponentContext.router extension function with initialStack argument.

And why is Children(routerState = router.state) an experimental API needing OptIn? That's in your tutorial as the only choice.

By the way, I think the example repo should be updated and it's still using 0.2.3, which misled me.

@arkivanov
Copy link
Owner

There is no clue for this one

You have to use one of the functions defined here: either with initialStack: () -> List argument, or with initialConfiguration: C argument.

So your code could be as follows (from the top of my head, there are possible mistakes):

@Composable
inline fun <reified C : Parcelable> rememberRouter(
    initialConfiguration: C,
    handleBackButton: Boolean = false,
): Router<C, Any> {
    val context = rememberComponentContext()

    return remember {
        context.router(
            initialConfiguration = initialConfiguration,
            handleBackButton = handleBackButton
        ) { configuration, _ ->
            configuration
        }
    }
}

or

@Composable
inline fun <reified C : Parcelable> rememberRouter(
    noinline initialStack: () -> List<C>,
    handleBackButton: Boolean = false,
): Router<C, Any> {
    val context = rememberComponentContext()

    return remember {
        context.router(
            initialStack = initialStack,
            handleBackButton = handleBackButton
        ) { configuration, _ ->
            configuration
        }
    }
}

And why is Children(routerState = router.state) an experimental API needing OptIn?

This is because the animations API (the animation argument) is experimental. It will become stable with the upcoming 1.0.0 release. See #110 for more information.

By the way, I think the example repo should be updated and it's still using 0.2.3, which misled me.

The approach described in the article is more like an example of what is possible in general. However this approach is discouraged by the Decompose library. Also some useful features (e.g. the nested navigation) are not covered by that article. The preferred way is described in another section of that tutorial, and is also being advised in the documentation. I will try to update the repo and the article, thanks for pointing that out!

@liplum
Copy link
Author

liplum commented Jun 16, 2022

Thank for your help! I finished the migration and it does work.
Also, I will check the official documentation of Decompose then.

@liplum liplum closed this as completed Jun 16, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants