Coder Social home page Coder Social logo

Comments (14)

raamcosta avatar raamcosta commented on May 18, 2024 1

I was working on a new release to support all the new versions but I really want to release this hotfix first.

Later today (or maybe tomorrow) I will make another release to support the new accompanist version.

from compose-destinations.

raamcosta avatar raamcosta commented on May 18, 2024 1

Done. Artifact with version 0.9.2-beta is available on maven central 🎉

Once again, thank you so much for finding this :)
Please check if that is solved for you when you remove accompanist.

As for the other crash you were having, it indeed seems like an issue with that library. Try the versions I'm using in the sample app:

    const val compose = "1.1.0-beta01"
    const val composeNavigation = "2.4.0-beta01"
    const val accompanist = "0.21.0-beta"

And let me know too if that works.

from compose-destinations.

raamcosta avatar raamcosta commented on May 18, 2024 1

Nice 🙂

Later today or tomorrow morning I'll be releasing the new version to work with latest accompanist.

It envolves some API changes (forced by changes on accompanist) and that's why I want some more time to test and document them.

from compose-destinations.

raamcosta avatar raamcosta commented on May 18, 2024 1

Closing this as it should be solved. Thank you so much 🙂

from compose-destinations.

raamcosta avatar raamcosta commented on May 18, 2024

Hi again @StephanSchuster!

In these cases, all navigation APIs from the official compose navigation applies.

You can do:
navController.navigate(Screen1.route) for example. If Screen1 does not have navigation arguments.
There is also a navigateTo extension function of NavController that accepts a Routed instance. So that would be:
navController.navigateTo(Screen1). This is just a convenience method, it does the same as using the jetpack component API one.

To get the navController you can use the rememberDestinationsNavController function. You then need to pass that navController to the DestinationsNavHost function.

from compose-destinations.

StephanSchuster avatar StephanSchuster commented on May 18, 2024

Thank you @raamcosta for your immediate response.

I guess it's too late. I was already watching the sources of the extension method you also mentioned and then missed the "...To()" and got confused. My mistake. All clear now. Maybe at some point a very simple but working example in the readme would help newbies like me. Your official sample has lots of non-navigation related code in it and the docs only mention code fragments.

More important: Now my app crashes.

java.lang.ClassCastException: java.util.LinkedHashSet cannot be cast to java.util.List
        at com.google.accompanist.navigation.animation.AnimatedNavHostKt.AnimatedNavHost$lambda-3(AnimatedNavHost.kt:388)
        at com.google.accompanist.navigation.animation.AnimatedNavHostKt.AnimatedNavHost(AnimatedNavHost.kt:165)
        at com.google.accompanist.navigation.animation.AnimatedNavHostKt.AnimatedNavHost(AnimatedNavHost.kt:91)
        at com.ramcosta.composedestinations.DestinationsNavHostKt.DestinationsNavHost(DestinationsNavHost.kt:49)
        at com.example.nav.ScreensKt.Scaffold(Screens.kt:30)

My versions:

composeVersion = '1.0.4'
accompanistVersion = '0.20.0'
composeNavigationVersion = '2.4.0-beta01'

That brings me to my last questions (for today):

  • Is this known?
  • How to fix it (assuming that I could freely choose versions)?
  • How dependent on specific versions will I be when using your lib in future?

from compose-destinations.

StephanSchuster avatar StephanSchuster commented on May 18, 2024

Okay, it seems to work after updating to the latest versions:

composeVersion = '1.0.5'
accompanistVersion = '0.20.2'
composeNavigationVersion = '2.4.0-beta02'

If possible, I would still appreciate a comment to my last question. Thanks.

from compose-destinations.

raamcosta avatar raamcosta commented on May 18, 2024

Yeah, the "To()" suffix is just there so that imports on the IDE don't get all wonky. I will add a sub section on the navigation section explaining navigation above the NavHost level.

Yes, that crash was not directly an issue with this library. If you were using those same versions and doing the navigation code manually, that crash would still happen.

Regarding the future and the versions, I don't expect there to be many restrictions. For now, since the APIs we rely on are not final, and there are a lot of changes happening in their implementation, I include a "tested versions" block in each release. But since this library works as a wrapper to other APIs, once those get stable that won't be needed anymore.

from compose-destinations.

StephanSchuster avatar StephanSchuster commented on May 18, 2024

Ah, alright. Understood. Thanks for clarification.

I now have the the following code with above versions:

@OptIn(ExperimentalAnimationApi::class)
@Composable
fun Scaffold() {
    Row(modifier = Modifier.fillMaxSize()) {
        val navController = rememberDestinationsNavController()

        DestinationsMenu(navController = navController)

        DestinationsNavHost(
            modifier = Modifier.fillMaxSize(),
            navController = navController
        )
    }
}

@Composable
fun DestinationsMenu(navController: NavController) {
    val backStackEntry by navController.currentBackStackEntryAsState()
    val destination = backStackEntry?.navDestination ?: NavGraphs.root.startDestination

    NavigationRail {
        NavGraphs.root.destinations.forEach {
            NavigationRailItem(
                icon = { Icon(Icons.Filled.Star, contentDescription = it.key) },
                label = { Text(it.key) },
                selected = it.value == destination,
                onClick = { navController.navigate(it.value.route) }
            )
        }
    }
}

The app starts and then immediately crashes:

java.lang.NoSuchMethodError: No static method AnimatedContent(Landroidx/compose/animation/core/Transition;Landroidx/compose/ui/Modifier;Lkotlin/jvm/functions/Function1;Landroidx/compose/ui/Alignment;Lkotlin/jvm/functions/Function4;Landroidx/compose/runtime/Composer;II)V in class Landroidx/compose/animation/AnimatedContentKt; or its super classes (declaration of 'androidx.compose.animation.AnimatedContentKt' appears in /data/app/~~5AEd6a9JA-Yz6TYBzgaeXA==/com.elektrobit.mad.template-4U9S7JjqsHbSKJj0LUx2tA==/base.apk)
        at com.google.accompanist.navigation.animation.AnimatedNavHostKt.AnimatedNavHost(AnimatedNavHost.kt:242)
        at com.google.accompanist.navigation.animation.AnimatedNavHostKt$AnimatedNavHost$10.invoke(Unknown Source:23)
        at com.google.accompanist.navigation.animation.AnimatedNavHostKt$AnimatedNavHost$10.invoke(Unknown Source:10)
        at androidx.compose.runtime.RecomposeScopeImpl.compose(RecomposeScopeImpl.kt:140)
        at androidx.compose.runtime.ComposerImpl.recomposeToGroupEnd(Composer.kt:2158)
        at androidx.compose.runtime.ComposerImpl.skipToGroupEnd(Composer.kt:2427)
        at androidx.compose.material.MaterialTheme_androidKt.PlatformMaterialTheme(MaterialTheme.android.kt:24)
        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.RecomposeScopeImpl.compose(RecomposeScopeImpl.kt:140)
        at androidx.compose.runtime.ComposerImpl.recomposeToGroupEnd(Composer.kt:2158)
        at androidx.compose.runtime.ComposerImpl.skipToGroupEnd(Composer.kt:2427)
        at androidx.compose.material.TextKt.ProvideTextStyle(Text.kt:266)
        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 com.example.navpoc.template.common.theme.ThemeKt$TemplateTheme$1.invoke(Theme.kt:32)
        at com.example.navpoc.template.common.theme.ThemeKt$TemplateTheme$1.invoke(Theme.kt:31)
        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 com.example.navpoc.template.common.theme.ThemeKt.TemplateTheme(Theme.kt:29)
        at com.example.navpoc.template.common.theme.ThemeKt$TemplateTheme$2.invoke(Unknown Source:10)
        at com.example.navpoc.template.common.theme.ThemeKt$TemplateTheme$2.invoke(Unknown Source:10)
        at androidx.compose.runtime.RecomposeScopeImpl.compose(RecomposeScopeImpl.kt:140)
        at androidx.compose.runtime.ComposerImpl.recomposeToGroupEnd(Composer.kt:2158)
        at androidx.compose.runtime.ComposerImpl.skipToGroupEnd(Composer.kt:2427)
        at androidx.compose.ui.platform.AbstractComposeView$ensureCompositionCreated$1.invoke(ComposeView.android.kt:252)
        at androidx.compose.ui.platform.AbstractComposeView$ensureCompositionCreated$1.invoke(ComposeView.android.kt:251)
        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)

This most probably has nothing to do with this library but with Accompanist navigation. Still, I wanted to ask if you have any idea.

I then removed the accompanist-navigation-animation dependency from my gradle file. To my understanding the code you generate is then different (right?) and I was hoping to get rid of above issue. But on build I then get the following error:

e: ...\app\build\generated\ksp\debug\kotlin\com\ramcosta\composedestinations\DestinationsNavHost.kt: (38, 77): Unresolved reference: NavBackStackEntry
e: ...\app\build\generated\ksp\debug\kotlin\com\ramcosta\composedestinations\DestinationsNavHost.kt: (69, 77): Unresolved reference: NavBackStackEntry
e: ...\app\build\generated\ksp\debug\kotlin\com\ramcosta\composedestinations\DestinationsNavHost.kt: (99, 77): Unresolved reference: NavBackStackEntry
e: ...\app\build\generated\ksp\debug\kotlin\com\ramcosta\composedestinations\DestinationsNavHost.kt: (119, 77): Unresolved reference: NavBackStackEntry

Looking at the generated code, I don't see an error:

package com.ramcosta.composedestinations

import androidx.compose.animation.*
import androidx.compose.material.*
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.navigation.NavBackStackEntry
import androidx.navigation.NavDestination
import androidx.navigation.NavGraphBuilder
import androidx.navigation.NavHostController
import androidx.navigation.compose.*
import androidx.navigation.Navigator
import com.ramcosta.composedestinations.spec.DestinationSpec
import com.ramcosta.composedestinations.spec.DestinationStyle
import com.ramcosta.composedestinations.spec.NavGraphSpec
import com.ramcosta.composedestinations.navigation.DependenciesContainerBuilder
import com.ramcosta.composedestinations.navigation.dependency



//region NavHost
/**
 * Like [androidx.navigation.compose.NavHost] but includes the destinations of [navGraph].
 * Composables annotated with `@Destination` will belong to a [NavGraph] inside [NavGraphs].
 *
 * @see [androidx.navigation.compose.NavHost]
 *
 * @param modifier [Modifier]
 * @param startDestination the start destination to use
 * @param navController [NavHostController]
 * @param dependenciesContainerBuilder lambda invoked when a destination gets navigated to. It allows
 * the caller to contribute certain dependencies that the destination can use.
 */
@Composable
fun DestinationsNavHost(
    modifier: Modifier = Modifier,
    startDestination: Destination = NavGraphs.root.startDestination,
    navController: NavHostController = rememberDestinationsNavController(),
    dependenciesContainerBuilder: @Composable DependenciesContainerBuilder.(NavBackStackEntry) -> Unit = {}
) {
    NavHost(
        navController = navController,
        startDestination = startDestination.route,
        modifier = modifier,
        route = NavGraphs.root.route,
    ) {
        addNavGraphDestinations(
            navGraphSpec = NavGraphs.root,
            addNavigation = addNavigation(),   
            addComposable = addComposable(navController, dependenciesContainerBuilder)
        )
    }
}
//endregion NavHost

//region NavController
/**
 * Wraps the correct `remember*NavController` method depending on
 * whether animations are available or not.
 */
@Composable
fun rememberDestinationsNavController(
    vararg navigators: Navigator<out NavDestination>
) = rememberNavController(*navigators)
//endregion

//region internals
private fun addComposable(
    navController: NavHostController,
    dependenciesContainerBuilder: @Composable DependenciesContainerBuilder.(NavBackStackEntry) -> Unit
): NavGraphBuilder.(DestinationSpec) -> Unit {
    return { destination ->
        destination as Destination
        when (val destinationStyle = destination.style) {
            is DestinationStyle.Default -> {
                addComposable(
                    destination,
                    navController,
                    dependenciesContainerBuilder
                )
            }

            is DestinationStyle.Dialog -> {
                addDialogComposable(
                    destinationStyle,
                    destination,
                    navController,
                    dependenciesContainerBuilder
                )
            }

            else -> throw RuntimeException("Should be impossible! Code gen should have failed if using a style for which you don't have the dependency")
        }
    }
}

private fun NavGraphBuilder.addComposable(
    destination: Destination,
    navController: NavHostController,
    dependenciesContainerBuilder: @Composable DependenciesContainerBuilder.(NavBackStackEntry) -> Unit
) {
    composable(
        route = destination.route,
        arguments = destination.arguments,
        deepLinks = destination.deepLinks
    ) { navBackStackEntry ->
        destination.Content(
            navController,
            navBackStackEntry
        ) {
            dependenciesContainerBuilder(navBackStackEntry)
        }
    }
}

private fun NavGraphBuilder.addDialogComposable(
    dialogStyle: DestinationStyle.Dialog,
    destination: Destination,
    navController: NavHostController,
    dependenciesContainerBuilder: @Composable DependenciesContainerBuilder.(NavBackStackEntry) -> Unit
) {
    dialog(
        destination.route,
        destination.arguments,
        destination.deepLinks,
        dialogStyle.properties
    ) { navBackStackEntry ->
        destination.Content(
            navController,
            navBackStackEntry
        ) { dependenciesContainerBuilder(navBackStackEntry) }
    }
}

private fun addNavigation(): NavGraphBuilder.(NavGraphSpec, NavGraphBuilder.() -> Unit) -> Unit {
    return { navGraph, builder ->
        navigation(
            navGraph.startDestination.route,
            navGraph.route
        ) {
            this.builder()
        }
    }
}




//endregion

Any idea?

from compose-destinations.

raamcosta avatar raamcosta commented on May 18, 2024

Daaamn, yes I know what was the problem 🙁

My bad with the latest version, I introduced the import for that in the accompanist specific imports 🤦
I definitely need to streamline my testing with and without accompanist so that this doesn't happen again.
I will release a hotfix for this right now, it should be up in maybe 30min or so.

Thanks again for everything. And I'm sorry about this. I will definitely take measures so that it doesn't happen again.

I will comment here once the new version is live on maven central.

from compose-destinations.

StephanSchuster avatar StephanSchuster commented on May 18, 2024

Oh wow, that sounds great.

The latest possible versions currently seem to be:

composeVersion = '1.1.0-beta02'                       <-- latest
composeNavigationVersion = '2.4.0-beta02'             <-- latest
accompanistVersion = '0.21.0-beta'                    <-- not latest

If you release another version anyways, would it be possible to make the latest accompanist 0.21.2-beta work? Currently your generated code does not compile with this.

from compose-destinations.

StephanSchuster avatar StephanSchuster commented on May 18, 2024

Thanks for your support.

With accompanist 0.21.0-beta the beta-01 and also the beta-02 of both compose libraries work. I tested them all. As said before, it did work even without your hotfix.

With accompanist 0.21.2-beta (latest version and said to be compatible with compose 1.1.0-beta02) I get compile issues with your library. Would be nice to get them fixed soon.

Regarding the Unresolved reference: NavBackStackEntry:
It occurs with:

composeVersion = '1.1.0-beta02'
composeNavigationVersion = '2.4.0-beta02'
accompanistVersion = '0.20.2'
composeDestinationsVersion = '0.9.1-beta'

It does not occur anymore with your HOTFIX:

composeVersion = '1.1.0-beta02'
composeNavigationVersion = '2.4.0-beta02'
accompanistVersion = '0.20.2'
composeDestinationsVersion = '0.9.2-beta'

from compose-destinations.

raamcosta avatar raamcosta commented on May 18, 2024

An thank you so much again for this 🙏

from compose-destinations.

raamcosta avatar raamcosta commented on May 18, 2024

0.9.4 is now up with support for the new accompanist version 🙂

Let me know how it goes!

from compose-destinations.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.