Giter VIP home page Giter VIP logo

voyager's Introduction

Maven metadata URL Android API kotlin ktlint License MIT


Voyager: Compose on Warp Speed

A multiplatform navigation library built for, and seamlessly integrated with, Jetpack Compose.

Create scalable Single-Activity apps powered by a pragmatic API:

class HomeScreenModel : ScreenModel {
    // ...
}

class HomeScreen : Screen {

    @Composable
    override fun Content() {
        val screenModel = rememberScreenModel<HomeScreenModel>()
        // ...
    }
}

class SingleActivity : ComponentActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        setContent {
            Navigator(HomeScreen())
        }
    }
}

Turn on the Warp Drive and enjoy the voyage 🖖

Documentation

See the project website for documentation and APIs.

Features

Samples

Stack API Android ViewModel ScreenModel Basic nav.
navigation-stack navigation-android-viewmodel navigation-screenmodel navigation-basic
BottomSheet nav. Tab nav. Multi-module nav. Nested nav.
navigation-bottom-sheet navigation-tab navigation-multi-module navigation-nested

voyager's People

Contributors

adrielcafe avatar aftabahmadtw avatar alaksion avatar arslan-charyyev-pc avatar cortinico avatar devnatan avatar devsrsouza avatar geworfener avatar ghostbear avatar hhariri avatar hm-tamim avatar kashif-e avatar mr3y-the-programmer avatar nvkleban avatar osrl avatar programadorthi avatar revxrsal avatar shusshu avatar syer10 avatar terrakok avatar williankl avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

voyager's Issues

Unable to parcelize parcelable objects

In the documentation here we are explained to use @parcelize and Parcelable however when doing so, the app throws an exception when you tap home, leave the app or open another Intent:

FATAL EXCEPTION: main Process: ca.redacted, PID: 10491 java.lang.RuntimeException: Parcelable encountered IOException writing serializable object (name = ca....redacted) at android.os.Parcel.writeSerializable(Parcel.java:2125) at android.os.Parcel.writeValue(Parcel.java:1895) at android.os.Parcel.writeList(Parcel.java:1104) at android.os.Parcel.writeValue(Parcel.java:1844) at android.os.Parcel.writeList(Parcel.java:1104) at android.os.Parcel.writeValue(Parcel.java:1844) at android.os.Parcel.writeArrayMapInternal(Parcel.java:987) at android.os.BaseBundle.writeToParcelInner(BaseBundle.java:1620) at android.os.Bundle.writeToParcel(Bundle.java:1303) at android.os.Parcel.writeBundle(Parcel.java:1056) at android.os.Parcel.writeValue(Parcel.java:1813) at android.os.Parcel.writeArrayMapInternal(Parcel.java:987) at android.os.BaseBundle.writeToParcelInner(BaseBundle.java:1620) at android.os.Bundle.writeToParcel(Bundle.java:1303) at android.os.Parcel.writeBundle(Parcel.java:1056) at android.os.Parcel.writeValue(Parcel.java:1813) at android.os.Parcel.writeArrayMapInternal(Parcel.java:987) at android.os.BaseBundle.writeToParcelInner(BaseBundle.java:1620) at android.os.Bundle.writeToParcel(Bundle.java:1303) at android.app.IActivityTaskManager$Stub$Proxy.activityStopped(IActivityTaskManager.java:4969) at android.app.servertransaction.PendingTransactionActions$StopInfo.run(PendingTransactionActions.java:145) at android.os.Handler.handleCallback(Handler.java:938) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loop(Looper.java:246) at android.app.ActivityThread.main(ActivityThread.java:8645) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:602) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1130) Caused by: java.io.NotSerializableException: ca...redacted at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1240) at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1604) at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1565) at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1488) at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1234) at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:354) at android.os.Parcel.writeSerializable(Parcel.java:2120) at android.os.Parcel.writeValue(Parcel.java:1895)  at android.os.Parcel.writeList(Parcel.java:1104)  at android.os.Parcel.writeValue(Parcel.java:1844)  at android.os.Parcel.writeList(Parcel.java:1104)  at android.os.Parcel.writeValue(Parcel.java:1844)  at android.os.Parcel.writeArrayMapInternal(Parcel.java:987)  at android.os.BaseBundle.writeToParcelInner(BaseBundle.java:1620)  at android.os.Bundle.writeToParcel(Bundle.java:1303)  at android.os.Parcel.writeBundle(Parcel.java:1056)  at android.os.Parcel.writeValue(Parcel.java:1813)  at android.os.Parcel.writeArrayMapInternal(Parcel.java:987)  at android.os.BaseBundle.writeToParcelInner(BaseBundle.java:1620)  at android.os.Bundle.writeToParcel(Bundle.java:1303)  at android.os.Parcel.writeBundle(Parcel.java:1056)  at android.os.Parcel.writeValue(Parcel.java:1813)  at android.os.Parcel.writeArrayMapInternal(Parcel.java:987)  at android.os.BaseBundle.writeToParcelInner(BaseBundle.java:1620)  at android.os.Bundle.writeToParcel(Bundle.java:1303)  at android.app.IActivityTaskManager$Stub$Proxy.activityStopped(IActivityTaskManager.java:4969)  at android.app.servertransaction.PendingTransactionActions$StopInfo.run(PendingTransactionActions.java:145)  at android.os.Handler.handleCallback(Handler.java:938)  at android.os.Handler.dispatchMessage(Handler.java:99)  at android.os.Looper.loop(Looper.java:246)  at android.app.ActivityThread.main(ActivityThread.java:8645)  at java.lang.reflect.Method.invoke(Native Method)  at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:602)  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1130) 

In fact the example given in the documentation doesn't work.
Versions used:

val voyager_version = 1.0.0-rc02

    implementation "cafe.adriel.voyager:voyager-navigator:$voyager_version"
    implementation "cafe.adriel.voyager:voyager-androidx:$voyager_version"
    implementation "cafe.adriel.voyager:voyager-hilt:$voyager_version"

id org.jetbrains.kotlin.android version 1.7.0 apply false

  ext {
        compose_ui_version = 1.2.0-rc01
        compose_compiler_version = 1.2.0
   }

I did see this thread: ##59 but even when using something like:

@Parcelize
data class NavParam(
    var firstName: String = "",
): Parcelable

data class NewScreen(
    val navParam: NavParam
) : Screen {
}

The app still crashes.

[Proposal] Pass default parameters into Screen Content() function

Hello, I'm trying to adopt your library into my pet project. I was faced with an issue, that the inner screen should consider padding from the parent screen.

Please take a look sample. I need to pass paddingValues into CurrentTab(). The Scaffold provides this value to prevent content overlapping.

TabNavigator(FlagsTab) { tabNavigator ->
            Scaffold(
                modifier = Modifier.systemBarsPadding(),
                topBar = {},
                content = { paddingValues ->
                    CurrentTab()
                },
                bottomBar = {
                    BottomNavigation {
                        TabNavigationItem(Tab1)
                        TabNavigationItem(Tab2)
                    }
                }
            )
        }

My suggestion is to make Screen interface like this with default parameters:

interface Screen : Serializable {

    val key: ScreenKey
        get() = this::class.qualifiedName
            ?: error("Default ScreenKey not found, please provide your own key")

    @Composable
    fun Content(
        modifier: Modifier = Modifier,
        paddingValues: PaddingValues = PaddingValues()
    )
}

Thanks a lot)

BottomSheetNavigator does not properly handle click outside to dismiss

When clicking outside the bottomsheet to close it, the navigator is not involved currently, meaning that it won't replace the stack leading to display issue on the next show + keeping the composables / viewmodel in memory.

Solution is to use the confirmStateChange parameter of the sheet state and when the target is Hidden, manually call the navigator hide and return false to not let the default handling happen.

Pass data between screens

My application has a case where it needs to pass a variable to a previous screen from the current screen. With fragments I have been using setFragmentResultListener api to do this, but with Voyager there is not a way to properly handle cases like this.

My suggestions:

  • A sample of a safe way to do this. since Voyager is more open than fragments about its API I imagine there could be a safe way to do this already that I haven't found
  • An API to handle use cases like this

LocalViewModelStoreOwner inside AndroidScreen should implement HasDefaultViewModelProviderFactory and return SavedStateViewModelFactory

When androidx.lifecycle.viewmodel.compose.viewModel() function is called inside plain ComponentActivity or Fragment, it uses ViewModelStoreOwner of activity/fragment which implements HasDefaultViewModelProviderFactory and returns SavedStateViewModelFactory. This allows using ViewModel that accepts SavedStateHandle or Application in constructor without any configuration.

If one then decides to migrate to Voyager library and use AndroidScreen, they would encounter runtime exceptions because AndroidScreen's ViewModelStoreOwner implementation doesn't implement HasDefaultViewModelProviderFactory which makes viewModel() use no arguments constructor.

AndroidScreen should use SavedStateViewModelFactory by default to match behaviour of ComponentActivity/Fragment (there also needs to be an API to pass Bundle of default state to SavedStateViewModelFactory).

1.0 RC2 AndroidScreenLifecycleOwner memory leak

Last version introduced a memory leak:

┬───
│ GC Root: Input or output parameters in native code
│
├─ dalvik.system.PathClassLoader instance
│    Leaking: NO (ScreenLifecycleStore↓ is not leaking and A ClassLoader is never leaking)
│    ↓ ClassLoader.runtimeInternalObjects
├─ java.lang.Object[] array
│    Leaking: NO (ScreenLifecycleStore↓ is not leaking)
│    ↓ Object[2112]
├─ cafe.adriel.voyager.core.lifecycle.ScreenLifecycleStore class
│    Leaking: NO (a class is never leaking)
│    ↓ static ScreenLifecycleStore.owners
│                                  ~~~~~~
├─ java.util.concurrent.ConcurrentHashMap instance
│    Leaking: UNKNOWN
│    Retaining 10.7 MB in 81204 objects
│    ↓ ConcurrentHashMap["Screen#11"]
│                       ~~~~~~~~~~~~~
├─ cafe.adriel.voyager.androidx.AndroidScreenLifecycleOwner instance
│    Leaking: UNKNOWN
│    Retaining 775 B in 28 objects
│    ↓ AndroidScreenLifecycleOwner.atomicContext
│                                  ~~~~~~~~~~~~~
├─ java.util.concurrent.atomic.AtomicReference instance
│    Leaking: UNKNOWN
│    Retaining 12 B in 1 objects
│    value instance of app.symfonik.ui.MainActivity with mDestroyed = true
│    ↓ AtomicReference.value
│                      ~~~~~
╰→ app.symfonik.ui.MainActivity instance
​     Leaking: YES (ObjectWatcher was watching this because app.symfonik.ui.MainActivity received Activity#onDestroy()
​     callback and Activity#mDestroyed is true)
​     Retaining 10.7 MB in 81168 objects
​     key = 2b6ebb8b-dc34-4653-bce5-8a807c33b146
​     watchDurationMillis = 6356
​     retainedDurationMillis = 1355
​     mApplication instance of app.symfonik.Application
​     mBase instance of android.app.ContextImpl

Hilt viewmodel + replace + transition = crash

So this is a tricky one.

Navigator(Screen1()) { navigator ->
                        SlideTransition(navigator)
                    }

class Screen1() : AndroidScreen {
    @Composable
    override fun Content() {
            val viewModel = getViewModel<Screen1ViewModel>()
            ....
            LocalNavigator.currentOrThrow.replace(Screen2())
    }
}

Will lead to a crash

    java.lang.IllegalArgumentException: SavedStateProvider with the given key is already registered
        at androidx.savedstate.SavedStateRegistry.registerSavedStateProvider(SavedStateRegistry.java:111)
        at androidx.lifecycle.SavedStateHandleController.attachToLifecycle(SavedStateHandleController.java:50)
        at androidx.lifecycle.SavedStateHandleController.create(SavedStateHandleController.java:70)
        at androidx.lifecycle.AbstractSavedStateViewModelFactory.create(AbstractSavedStateViewModelFactory.java:67)
        at androidx.lifecycle.AbstractSavedStateViewModelFactory.create(AbstractSavedStateViewModelFactory.java:84)
        at dagger.hilt.android.internal.lifecycle.HiltViewModelFactory.create(HiltViewModelFactory.java:109)

From a quick look the viewmodel is properly cleared, but it seems Voyager tries to re access the SaveStateProvider later with the same key (obviously as it's the same composable).

There's no issue without enabling transitions, so this looks like some wrong order of calls, whatever access the savestate during the transition should do it before the full removal of the composable to avoid trying to reuse the key.
There's also no problem when just pushing a new screen. This works without using hitviewmodel.

Beta13 hiltviewmodel crash when navigating back to same destination

So the fix for the replace issue have now generated a worse issue.

    java.lang.IllegalArgumentException: SavedStateProvider with the given key is already registered
        at androidx.savedstate.SavedStateRegistry.registerSavedStateProvider(SavedStateRegistry.java:111)
        at androidx.lifecycle.SavedStateHandleController.attachToLifecycle(SavedStateHandleController.java:50)
        at androidx.lifecycle.SavedStateHandleController.create(SavedStateHandleController.java:70)
        at androidx.lifecycle.AbstractSavedStateViewModelFactory.create(AbstractSavedStateViewModelFactory.java:67)
        at androidx.lifecycle.AbstractSavedStateViewModelFactory.create(AbstractSavedStateViewModelFactory.java:84)
        at dagger.hilt.android.internal.lifecycle.HiltViewModelFactory.create(HiltViewModelFactory.java:109)
        at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.kt:171)
        at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.kt:139)

it will crash whenever you navigate again to a destination.

So push(Screen) pop() push(Screen) will crash.

As said in #17 the root issue is more about transitions and autodispose happening too early.

There's side effects too with ScreenModel that are disposed too early (even before the next screen is composed). This can corrupt what is displayed during transition and cause hard to diagnose side effects.

This is more a core issue for @adrielcafe than an hilt specific one. (The "fix" stills needs to be reverted)
While we can disable autodispose at the navigator level we have no way to built custom transitions that would do a proper dispose after the end of the transition.

Wrap Navigator with AnimatedVisibility produce reset navigator to initial screen

Hi, many thanks for your library. I have tried it a bit and it's very powerful.

I have noticed when I wrap Navigator with AnimatedVisibility it is reset to the initial screen.

I created my own scaffold with slots, I need to use different navigators in each slot. In one slot in the scaffold root, I need to use AnimatedVisibility to produce hide/collapse animation, and in this slot I need to maintain some navigation. So after I create navigation in that AnimatedVisibility composable I have noticed that when it exit to the invisible state navigator also resets its state to the initial state.

Can you provide some ideas of how I can achieve some animation around box that contains navigator ?

AndroidScreen() ViewModel retained after activity is finished

I have an issue of AndroidScreens ViewModel being retained when activity is finished. This seems to only happen to root navigator screen. So when I am in my root view and press back, activity finishes, when I open the app again, screen gets the same ViewModel that has some state retained. Using regular Screen doesn't have this issue

Save restoration doesn't work when Android destroys activity and create it again.

When Android destroys activity Voyager serialize screens and then restore them. But they now are different objects and Voyager uses them as "key" for "navigator.stateHolder.SaveableStateProvider" I think that is why Voyager can't restore state after activity recreation. (Same for tabNavigator.stateHolder.SaveableStateProvider(currentTab))

Re: Wanted to show you project I made with your library

Hi @adrielcafe, I wanted to show you my sample app I made with Voyager: https://github.com/JohnBuhanan/MVI-Public

I studied a dozen github repos and felt like yours was closest to what I wanted.

Three things I thought you might find interesting:

  1. I wrapped your Navigator so that I can do routing from ViewModels.
  2. Each feature contains an api gradle module and an impl gradle module. The impls can be commented out from settings.gradle and app.gradle to unload them from Android Studio indexing and gradle builds. This allows scaling for massively multi-module apps.
  3. I used reflection to get access to the "internal factories" of ScreenRegistry.

Biggest thing I am thinking about now is best way to "navigate for result".

Nested BackHandler

In theory, the order of nested onBack functions should be from innermost up the chain. But in the current behavior, the opposite is true.

To repeat the steps, go to the nested navigation example, open 1 screen in each navigator and press the system back button 3 times.

[Feature Request] PopRoot()

Would be a useful function to close a nested navigation. For example, I have a flow for authorization with two screens, for entering a phone number and a password, when you call popUntilRoot() on the last screen, the screens are pulled out of the stack one by one and you can see how the keyboard blinks from the previous screens. It was convenient to have a mechanism to remove the entire chain at once.

Does ability to navigation not from composable function?

I wonder is has ability to navigate not from Composable? For example if i want navigate from viewModel or UseCase class.
How i see that i can get navigator instance with LocalNavigator.currentOrThrow only from Composable function.

ViewModel never cleared

Hi. I am using Voyager to navigate in a project built on the Orbit MVI and Koin libraries. Orbit requires a ViewModel to store the container, so i can't use ScreenModel. I am injecting the viewModel using the getVievModel from Koin in @composable override fun Content(). The problem is that when i'm leaving the screen using the pop() function, the viewModel is not cleared over the app life cycle and if i open the same screen again i have the same viewModel with preloaded data. How to deal with this? Thank you in advance!

Crash durring animation Key com.github.navtest.ScreenFoo was used multiple times

Hello, my application crashes when changing screens with animated content.
I use code from examples. I think is a problem for all users.

kotlin_version '1.5.31'
voyager_version = "1.0.0-beta13"
compose_version = '1.1.0-alpha06'

Repository for reproduce - https://github.com/jershell/voyager-bug-reproduce/tree/main

Flow

  1. Click on the button "to Bar"
  2. Not awaiting finishing of animation fast click on the button "to Foo"
    Have a crash

java.lang.IllegalArgumentException: Key com.github.navtest.ScreenFoo was used multiple times

Stacktrace

E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.github.navtest, PID: 2788
    java.lang.IllegalArgumentException: Key com.github.navtest.ScreenFoo was used multiple times 
        at androidx.compose.runtime.saveable.SaveableStateHolderImpl$SaveableStateProvider$1$1.invoke(SaveableStateHolder.kt:89)
        at androidx.compose.runtime.saveable.SaveableStateHolderImpl$SaveableStateProvider$1$1.invoke(SaveableStateHolder.kt:88)
        at androidx.compose.runtime.DisposableEffectImpl.onRemembered(Effects.kt:81)
        at androidx.compose.runtime.CompositionImpl$RememberEventDispatcher.dispatchRememberObservers(Composition.kt:802)
        at androidx.compose.runtime.CompositionImpl.applyChanges(Composition.kt:647)
        at androidx.compose.runtime.Recomposer$runRecomposeAndApplyChanges$2$2.invoke(Recomposer.kt:488)
        at androidx.compose.runtime.Recomposer$runRecomposeAndApplyChanges$2$2.invoke(Recomposer.kt:425)
        at androidx.compose.ui.platform.AndroidUiFrameClock$withFrameNanos$2$callback$1.doFrame(AndroidUiFrameClock.android.kt:34)
        at androidx.compose.ui.platform.AndroidUiDispatcher.performFrameDispatch(AndroidUiDispatcher.android.kt:109)
        at androidx.compose.ui.platform.AndroidUiDispatcher.access$performFrameDispatch(AndroidUiDispatcher.android.kt:41)
        at androidx.compose.ui.platform.AndroidUiDispatcher$dispatchCallback$1.doFrame(AndroidUiDispatcher.android.kt:69)
        at android.view.Choreographer$CallbackRecord.run(Choreographer.java:964)
        at android.view.Choreographer.doCallbacks(Choreographer.java:790)
        at android.view.Choreographer.doFrame(Choreographer.java:721)
        at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:951)
        at android.os.Handler.handleCallback(Handler.java:883)
        at android.os.Handler.dispatchMessage(Handler.java:100)
        at android.os.Looper.loop(Looper.java:214)
        at android.app.ActivityThread.main(ActivityThread.java:7356)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)

Cannot use stateIn operator inside ScreenModel

Using stateIn operator inside ScreenModel using built-in coroutineScope cause a crash with java.lang.IllegalStateException: ScreenModel not found. However, this exception doesn't happen if self-created Coroutine scope is used.
Example code,

class TestScreen : Screen {
    @Composable
    override fun Content() {
        val sm = rememberScreenModel { TestScreenModel() }
        val msg by sm.msg.collectAsState()
        Text(msg)
    }
}

class TestScreenModel : ScreenModel {
    val msg = msgFlow.stateIn(coroutineScope, SharingStarted.Lazily, "")
}

val msgFlow = listOf("Hello", "world!").asFlow()

Drop state / restart screen

This is probably a feature request unless I missed something and certainly not a vital one.

Is there a way to restart a screen fresh?

For example in a tab screen I start a nested navigation, when pressing the same tab button I'd like to return to the home of that tab but in a fresh state (so not scrolled for example).
I can have the screen provide their nested navigator via an interface and for example use popUntilRoot but as expected the root screen is restored in it's previous state (normal wanted default behavior).

In some cases I'd like to be able to restart that screen fresh

1.0 RC01 side effect on tab navigation

The fix (#55) have the side effect of now fully unloading the view models when navigating between tabs.

While the fix is normal and wanted, due to the current limitations of LazyList not proposing any proper way to delay the state restoration, this makes restoring scroll position insanely complex until they propose something.

It would be nice to have a way to opt out or a workaround for this use case.

Support state restoration?

Hello and thanks for the library.

I am an engineer from Compose team at Google and wanted to mention that there is an expectation from the navigation library in Compose that this will save the inner state of the components which are currently in the backstack. Examples are the scrolling position of the LazyColumn should be restored when you go from screen with the list to the second screen and then go back to the list screen.
Other navigation libraries like the official one from androidx of Decompose support it as they use the special API designed to make is simpler: https://developer.android.com/reference/kotlin/androidx/compose/runtime/saveable/SaveableStateHolder
Please let me know if you will have any questions, thanks!

ScreenModel working not properly

It's look like ScreenModel logic working wrong. Overriden onDispose method in root screen not called when we leave this screen.

Cannot inline bytecode built with JVM target 11 into bytecode

Hi.

I have a project that is targeting android and desktop.

I would like to use rememberScreenModel in Screen but unfortunately, I'm getting this error

Cannot inline bytecode built with JVM target 11 into bytecode that is being built with JVM target 1.8. Please specify proper '-jvm-target' option

class Detail : Screen, KoinComponent {
    @Composable
    override fun Content() {
        val model = rememberScreenModel<LoginModel> { get() }
        val state: LoginState by model.state.collectAsState()
        Button(onClick = { model.proccessData() }) {
            Text("It Is Detail Screen ")
        }
    }
}

Any suggestions?

Seperate Animated Content

I use a Scaffold for my screens and I have my scaffold wrapping my screen content, with interfaces that handle different types of screens

Navigator(startScreen) {
    CurrentScreenWithScaffold(it)
}
@Composable
fun CurrentScreenWithScaffold(navigator: Navigator) {
    val currentScreen = navigator.lastItem

    navigator.stateHolder.SaveableStateProvider(currentScreen.key) {
        Scaffold(
            topBar = {
                if (currentScreen is AppBarScreen) {
                    currentScreen.AppBar()
                }
            },
            bottomBar = {
                BottomNav(
                    isVisible = currentScreen is BottomNavScreen
                )
            }
        ) {
            Box(Modifier.padding(it)) {
                currentScreen.Content()
            }
        }
    }
}

I want to be able to animate only currentScreen.Content(), but I cant do that because of navigator.stateHolder.SaveableStateProvide, it can only be declared once but I also need it to wrap my currentScreen.AppBar() as it needs access to my ViewModel. I cannot find a way that satisfies my requirements with the current API.

Lifecycle onPause/onStop/onDestory are never called

While testing my app with Voyager I noticed some of my AndroidView states were never being saved. Investigating that lead me to my LifecycleObserver's never filling the bundle contained in my rememberSavable variable. I then logged the states that the lifecycle observer goes through and noticed that only onCreate/OnStart/OnResume are ever called, and never the last 3.

Here are the test composables I used

@Composable
private fun rememberLoggingLifecycleObserver(): LifecycleEventObserver {
    val bundle = rememberSaveable { Bundle() }
    return remember {
        LifecycleEventObserver { _, event ->
            when (event) {
                Lifecycle.Event.ON_CREATE -> {
                    logcat("Lifecycle") { "OnCreate" }
                    logcat("Lifecycle") { bundle.keySet().joinToString() }
                    bundle.clear()
                }
                Lifecycle.Event.ON_START -> logcat("Lifecycle") { "OnStart" }
                Lifecycle.Event.ON_RESUME -> logcat("Lifecycle") { "OnResume" }
                Lifecycle.Event.ON_PAUSE -> logcat("Lifecycle") { "OnPause" }
                Lifecycle.Event.ON_STOP -> {
                    logcat("Lifecycle") { "OnStop" }
                    bundle.putAll(bundleOf("Yes" to "1200"))
                }
                Lifecycle.Event.ON_DESTROY -> logcat("Lifecycle") { "OnDestroy" }
                else -> throw IllegalStateException()
            }
        }
    }
}
@Composable
fun SetupLoggerLifecycleObserver() {
    val loggerObserver = rememberLoggingLifecycleObserver()
    val lifecycle = LocalLifecycleOwner.current.lifecycle
    DisposableEffect(lifecycle) {
        lifecycle.addObserver(loggerObserver)
        onDispose {
            // lifecycle.removeObserver(loggerObserver)
        }
    }
}

App crashing during minimization.

Minimizing App causing crash. Here is the error report:

Process: media.uqab.planit, PID: 6479
    java.lang.RuntimeException: Parcelable encountered IOException writing serializable object (name = media.uqab.planit.task.ui.screen.AllTaskScreen)
        at android.os.Parcel.writeSerializable(Parcel.java:1833)
        at android.os.Parcel.writeValue(Parcel.java:1780)
        at android.os.Parcel.writeList(Parcel.java:1045)
        at android.os.Parcel.writeValue(Parcel.java:1729)
        at android.os.Parcel.writeList(Parcel.java:1045)
        at android.os.Parcel.writeValue(Parcel.java:1729)
        at android.os.Parcel.writeArrayMapInternal(Parcel.java:928)
        at android.os.BaseBundle.writeToParcelInner(BaseBundle.java:1584)
        at android.os.Bundle.writeToParcel(Bundle.java:1253)
        at android.os.Parcel.writeBundle(Parcel.java:997)
        at android.os.Parcel.writeValue(Parcel.java:1698)
        at android.os.Parcel.writeArrayMapInternal(Parcel.java:928)
        at android.os.BaseBundle.writeToParcelInner(BaseBundle.java:1584)
        at android.os.Bundle.writeToParcel(Bundle.java:1253)
        at android.os.Parcel.writeBundle(Parcel.java:997)
        at android.os.Parcel.writeValue(Parcel.java:1698)
        at android.os.Parcel.writeArrayMapInternal(Parcel.java:928)
        at android.os.BaseBundle.writeToParcelInner(BaseBundle.java:1584)
        at android.os.Bundle.writeToParcel(Bundle.java:1253)
        at android.app.IActivityTaskManager$Stub$Proxy.activityStopped(IActivityTaskManager.java:4505)
        at android.app.servertransaction.PendingTransactionActions$StopInfo.run(PendingTransactionActions.java:145)
        at android.os.Handler.handleCallback(Handler.java:883)
        at android.os.Handler.dispatchMessage(Handler.java:100)
        at android.os.Looper.loop(Looper.java:214)
        at android.app.ActivityThread.main(ActivityThread.java:7356)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)
     Caused by: java.io.NotSerializableException: media.uqab.planit.task.ui.activity.TaskActivity
        at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1240)
        at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1604)
        at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1565)
        at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1488)
        at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1234)
        at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1604)
        at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1565)
        at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1488)
        at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1234)
        at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:354)
        at android.os.Parcel.writeSerializable(Parcel.java:1828)
        at android.os.Parcel.writeValue(Parcel.java:1780at android.os.Parcel.writeList(Parcel.java:1045at android.os.Parcel.writeValue(Parcel.java:1729at android.os.Parcel.writeList(Parcel.java:1045at android.os.Parcel.writeValue(Parcel.java:1729at android.os.Parcel.writeArrayMapInternal(Parcel.java:928at android.os.BaseBundle.writeToParcelInner(BaseBundle.java:1584at android.os.Bundle.writeToParcel(Bundle.java:1253at android.os.Parcel.writeBundle(Parcel.java:997at android.os.Parcel.writeValue(Parcel.java:1698at android.os.Parcel.writeArrayMapInternal(Parcel.java:928at android.os.BaseBundle.writeToParcelInner(BaseBundle.java:1584at android.os.Bundle.writeToParcel(Bundle.java:1253at android.os.Parcel.writeBundle(Parcel.java:997at android.os.Parcel.writeValue(Parcel.java:1698at android.os.Parcel.writeArrayMapInternal(Parcel.java:928at android.os.BaseBundle.writeToParcelInner(BaseBundle.java:1584at android.os.Bundle.writeToParcel(Bundle.java:1253at android.app.IActivityTaskManager$Stub$Proxy.activityStopped(IActivityTaskManager.java:4505at android.app.servertransaction.PendingTransactionActions$StopInfo.run(PendingTransactionActions.java:145at android.os.Handler.handleCallback(Handler.java:883at android.os.Handler.dispatchMessage(Handler.java:100at android.os.Looper.loop(Looper.java:214at android.app.ActivityThread.main(ActivityThread.java:7356at java.lang.reflect.Method.invoke(Native Methodat com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930

My Implementation:

Activity:

@AndroidEntryPoint
class TaskActivity: AppCompatActivity() {

    @OptIn(ExperimentalAnimationApi::class)
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        window.decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
        window.statusBarColor = Color.White.toArgb()

        setContent {
            Navigator(
                screen = AllTaskScreen(
                    onBackPress = { finish() }
                )
            ) { navigation ->
                ScaleTransition(navigator = navigation)
            }
        }
    }
}

AllTaskScreen:

class AllTaskScreen(
    private val onBackPress: () -> Unit = {}
): AndroidScreen() {

    @Composable
    override fun Content() {
        val viewModel = getViewModel<TaskViewModel>()
        val navigator = LocalNavigator.currentOrThrow

        // ... rest of the compose functions
    }
}

Hilt support

    val viewModel by hiltViewModel<MyViewModel>() doesnt work inside the @Composable Content function

Unable to declare screens on commonMain

I'm running into a weird issue with this library, that I haven't yet run into with other multiplatform libraries

I have a multiplatform module that targets android and desktop, which is setup like

import org.jetbrains.compose.compose

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

kotlin {
  android { .. }

  jvm("desktop") { .. }

  sourceSets {
    val commonMain by getting {
      dependencies {
        implementation(compose.runtime)
        ..
        implementation(Adriel.voyagerNavigator)
        implementation(Adriel.voyagerTabNavigator)
      }
    }

    val androidMain by getting { .. }
    val desktopMain by getting { .. }
  }
}

However, when I try to declare any screens in the commonMain, I get
Screen Shot 2022-02-21 at 4 18 16 pm

If I move to the declaration to desktopMain, it works just fine. Any idea why is this happening 🤔

Screen Model test Exception


    fun login(email: String, password: String) = coroutineScope.launch {
        val userCredentials = UserCredentials(email, password)
        logInUseCase.invoke(userCredentials)
    }
    @Test
    fun `on login success state is SignIn`() = runTest {
        loginModel.login("email", "password")
        loginModel.state
            .take(1)
            .onEach { assertEquals(it::class.simpleName, AuthState.SignedIn::class.simpleName) }
            .collect()
    }
java.lang.IllegalStateException: ScreenModel not found: ui.login.LoginModel
	at cafe.adriel.voyager.core.model.ScreenModelStore.getDependencyKey(ScreenModelStore.kt:39)
	at com.netguru.common.ScreenExtensionsKt.getModelScope(ScreenExtensions.kt:29)
	at ui.login.LoginModel.login(LoginModel.kt:19)
	at ui.LoginModelTest$on login success state is SignIn$1.invokeSuspend(LoginModelTest.kt:40)
	at ui.LoginModelTest$on login success state is SignIn$1.invoke(LoginModelTest.kt)
	at ui.LoginModelTest$on login success state is SignIn$1.invoke(LoginModelTest.kt)
	at kotlinx.coroutines.test.TestBuildersKt__TestBuildersKt$runTestCoroutine$2.invokeSuspend(TestBuilders.kt:208)
	at kotlinx.coroutines.test.TestBuildersKt__TestBuildersKt$runTestCoroutine$2.invoke(TestBuilders.kt)
	at kotlinx.coroutines.test.TestBuildersKt__TestBuildersKt$runTestCoroutine$2.invoke(TestBuilders.kt)
	at kotlinx.coroutines.intrinsics.UndispatchedKt.startCoroutineUndispatched(Undispatched.kt:55)
	at kotlinx.coroutines.CoroutineStart.invoke(CoroutineStart.kt:112)
	at kotlinx.coroutines.AbstractCoroutine.start(AbstractCoroutine.kt:126)
	at kotlinx.coroutines.test.TestBuildersKt__TestBuildersKt.runTestCoroutine(TestBuilders.kt:207)
	at kotlinx.coroutines.test.TestBuildersKt.runTestCoroutine(Unknown Source)
	at kotlinx.coroutines.test.TestBuildersKt__TestBuildersKt$runTest$1$1.invokeSuspend(TestBuilders.kt:167)
	at kotlinx.coroutines.test.TestBuildersKt__TestBuildersKt$runTest$1$1.invoke(TestBuilders.kt)
	at kotlinx.coroutines.test.TestBuildersKt__TestBuildersKt$runTest$1$1.invoke(TestBuilders.kt)
	at kotlinx.coroutines.test.TestBuildersJvmKt$createTestResult$1.invokeSuspend(TestBuildersJvm.kt:13)
	at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
	at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
	at kotlinx.coroutines.EventLoopImplBase.processNextEvent(EventLoop.common.kt:279)
	at kotlinx.coroutines.BlockingCoroutine.joinBlocking(Builders.kt:85)
	at kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking(Builders.kt:59)
	at kotlinx.coroutines.BuildersKt.runBlocking(Unknown Source)
	at kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking$default(Builders.kt:38)
	at kotlinx.coroutines.BuildersKt.runBlocking$default(Unknown Source)
	at kotlinx.coroutines.test.TestBuildersJvmKt.createTestResult(TestBuildersJvm.kt:12)
	at kotlinx.coroutines.test.TestBuildersKt__TestBuildersKt.runTest(TestBuilders.kt:166)
	at kotlinx.coroutines.test.TestBuildersKt.runTest(Unknown Source)
	at kotlinx.coroutines.test.TestBuildersKt__TestBuildersKt.runTest(TestBuilders.kt:154)
	at kotlinx.coroutines.test.TestBuildersKt.runTest(Unknown Source)
	at kotlinx.coroutines.test.TestBuildersKt__TestBuildersKt.runTest$default(TestBuilders.kt:147)
	at kotlinx.coroutines.test.TestBuildersKt.runTest$default(Unknown Source)
	at ui.LoginModelTest.on login success state is SignIn(LoginModelTest.kt:39)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:566)
	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
	at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.runTestClass(JUnitTestClassExecutor.java:110)
	at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.execute(JUnitTestClassExecutor.java:58)
	at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.execute(JUnitTestClassExecutor.java:38)
	at org.gradle.api.internal.tasks.testing.junit.AbstractJUnitTestClassProcessor.processTestClass(AbstractJUnitTestClassProcessor.java:62)
	at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.processTestClass(SuiteTestClassProcessor.java:51)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:566)
	at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:36)
	at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
	at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:33)
	at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:94)
	at com.sun.proxy.$Proxy2.processTestClass(Unknown Source)
	at org.gradle.api.internal.tasks.testing.worker.TestWorker$2.run(TestWorker.java:176)
	at org.gradle.api.internal.tasks.testing.worker.TestWorker.executeAndMaintainThreadName(TestWorker.java:129)
	at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:100)
	at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:60)
	at org.gradle.process.internal.worker.child.ActionExecutionWorker.execute(ActionExecutionWorker.java:56)
	at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:133)
	at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:71)
	at worker.org.gradle.process.internal.worker.GradleWorkerMain.run(GradleWorkerMain.java:69)
	at worker.org.gradle.process.internal.worker.GradleWorkerMain.main(GradleWorkerMain.java:74)

I can't use rememberScreenModel or ScreenModelStore.getOrPut in the test so that's why the error is thrown. Any idea how to work around this? @adrielcafe @terrakok @programadorthi @DevSrSouza

Compose Web Support?

Any plans for Compose Web Support? The big thing about navigating with web is browser url / paths need to be supported.

Expose flow of current screens

Hello, I'm currently trying to execute some logic based on current screen, but I can't find any callback that would give me current screen. Would be really nice if there is a way to expose flow of current screens. I would need such functionality for all navigators (tab, bottomSheet and regular navigator)

Crash when Screen or Tab has lambda parameter

Hello, I have faced with issue.
Steps to reproduce:

  1. Pass lambda parameter in Screen or Tab
  2. Minimize application (go to launch screen f.e)
  3. Observe crash 🙁

Version: 1.0.0-rc01
Sample reproducable project: https://github.com/egorikftp/VoyagerCrash

Crash log:

java.lang.RuntimeException: Parcelable encountered IOException writing serializable object (name = com.egoriku.voyagercrash.HomeTab)
        at android.os.Parcel.writeSerializable(Parcel.java:2165)
        at android.os.Parcel.writeValue(Parcel.java:1931)
        at android.os.Parcel.writeList(Parcel.java:1140)
        at android.os.Parcel.writeValue(Parcel.java:1880)
        at android.os.Parcel.writeList(Parcel.java:1140)
        at android.os.Parcel.writeValue(Parcel.java:1880)
        at android.os.Parcel.writeArrayMapInternal(Parcel.java:1023)
        at android.os.BaseBundle.writeToParcelInner(BaseBundle.java:1620)
        at android.os.Bundle.writeToParcel(Bundle.java:1304)
        at android.os.Parcel.writeBundle(Parcel.java:1092)
        at android.os.Parcel.writeValue(Parcel.java:1849)
        at android.os.Parcel.writeArrayMapInternal(Parcel.java:1023)
        at android.os.BaseBundle.writeToParcelInner(BaseBundle.java:1620)
        at android.os.Bundle.writeToParcel(Bundle.java:1304)
        at android.os.Parcel.writeBundle(Parcel.java:1092)
        at android.os.Parcel.writeValue(Parcel.java:1849)
        at android.os.BaseBundle.dumpStats(BaseBundle.java:1690)
        at android.os.BaseBundle.dumpStats(BaseBundle.java:1727)
        at android.app.servertransaction.PendingTransactionActions$StopInfo.run(PendingTransactionActions.java:150)
        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:7870)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1003)
     Caused by: java.io.NotSerializableException: androidx.compose.material.DrawerState
        at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1240)
        at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1604)
        at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1565)
        at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1488)
        at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1234)
        at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1604)
        at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1565)
        at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1488)
        at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1234)
        at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:354)
        at android.os.Parcel.writeSerializable(Parcel.java:2160)
        at android.os.Parcel.writeValue(Parcel.java:1931at android.os.Parcel.writeList(Parcel.java:1140at android.os.Parcel.writeValue(Parcel.java:1880at android.os.Parcel.writeList(Parcel.java:1140at android.os.Parcel.writeValue(Parcel.java:1880at android.os.Parcel.writeArrayMapInternal(Parcel.java:1023at android.os.BaseBundle.writeToParcelInner(BaseBundle.java:1620at android.os.Bundle.writeToParcel(Bundle.java:1304at android.os.Parcel.writeBundle(Parcel.java:1092at android.os.Parcel.writeValue(Parcel.java:1849at android.os.Parcel.writeArrayMapInternal(Parcel.java:1023at android.os.BaseBundle.writeToParcelInner(BaseBundle.java:1620at android.os.Bundle.writeToParcel(Bundle.java:1304at android.os.Parcel.writeBundle(Parcel.java:1092at android.os.Parcel.writeValue(Parcel.java:1849at android.os.BaseBundle.dumpStats(BaseBundle.java:1690at android.os.BaseBundle.dumpStats(BaseBundle.java:1727at android.app.servertransaction.PendingTransactionActions$StopInfo.run(PendingTransactionActions.java:150at android.os.Handler.handleCallback(Handler.java:938at android.os.Handler.dispatchMessage(Handler.java:99at android.os.Looper.loopOnce(Looper.java:201at android.os.Looper.loop(Looper.java:288at android.app.ActivityThread.main(ActivityThread.java:7870at java.lang.reflect.Method.invoke(Native Methodat com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1003

screen model doesn't survive the configuration changes

I try use Screen + ScreenModel + Hilt.

I create Screen like this:

object SearchScreen : Screen {

    @Composable
    override fun Content() {
        val screenModel = getScreenModel<SearchScreenModel>()
        Log.e("!!!!","!!!!Use screenmodel: $screenModel")
        SearchScreen(screenModel)
    }
}

And my ScreenModel:

class SearchScreenModel @Inject constructor(
    private val searchUseCase: SearchUseCase
) : ScreenModel {
   //Some code
}

But when i rotate my phone screen model recreated. Shouldn't the screen model survive the configuration changes? OR am I doing something wrong?

BottomSheet voyager back handling error

Currently the BackHandler is handled as

    BackHandler(
        enabled = sheetState.isVisible,

This causes problems about the order of the backhandlers when others views have registered a BackHandler after the bottomsheet navigator as they will get the event first and will act on it before the BottomSheet.

The proper way is to add the back handler only when the sheet is visible, meaning it's always added last and will have the priority.

So

if (sheetState.isVisible) {
     BackHandler(

Allow disabling state restoration

I have cases where state restoration is either not desirable or not worth implementing the serialization for. Please provide a way to disable state restoration, either globally through Navigator or on a per-screen basis through Screen. If the app is closed from a screen that is not restorable it should use the initial screen on startup.

Composition flickers when using Transitions

I'm attempting to migrate my app over to use Voyager, and I'm a big fan so far. One thing I'm struggling with is transitions. While using a SlideTransition, some of my screens "flicker" (get recomposed multiple times) and causes visual jitter. I understand that using a transition may cause a Composable to re-compose multiple times, but it seems like it shouldn't be visible to the user the way I'm seeing it.

Here is the basic code for what I'm doing without the transition:

setContent {
            LunaTheme {
                BottomSheetNavigator {
                    Navigator(screen = HomeScreen())
                }
        }
}  

and with transition:

setContent {
            LunaTheme {
                BottomSheetNavigator {

                    Navigator(screen = HomeScreen()) { navigator ->
                        SlideTransition(navigator = navigator)
                    }
                }
        }
}

and here are the results I'm getting. I have a function on each screen that logs when a composable is re-composed as well as the number of times that function has been recomposed. A number 0 indicates that the composable was remade from scratch, as opposed to just being re-composed because of a variable change.

Without transition:

In the video you can see that things navigate properly (the detail screen is just a loading spinner), and when navigating back to the home screen using the system back button, everything looks fine. In the logs you can see the HomeScreen is only recomposed once when returning from the BookDetailScreen.

Video: https://user-images.githubusercontent.com/25214257/167847261-ddd3dc87-22d1-4d06-8fe4-1982f62c4e11.mp4

Screen Shot 2022-05-11 at 8 07 30 AM

With transition:

You can see in this video that the loading spinner on the detail page gets completely restarted once, and when returning to the home screen, that screen also gets completely reloaded once, creating this visual jitter. You can also see in the logs (which also include the stack each time a navigation is performed) that when navigating to the detail page, it is re-composed from scratch with a value of zero in the logs four times, and the same happens when returning to the HomeScreen, it's restarted four times.

Video: https://user-images.githubusercontent.com/25214257/167847831-1c2ea9af-ac48-4fa1-aecb-240f7b7af403.mp4

Screen Shot 2022-05-11 at 8 06 53 AM

I'm not sure if I'm misusing the Transition here, or if this is a bug in the library, so any help would be much appreciated!

rememberSaveable doesn't work since 1.0.0-beta08

To reproduce this issue, just enable "Dont't keep activites" and use this test screen.

class TestScreen : Screen {
    @Composable
    override fun Content() {
        var text by rememberSaveable {
            mutableStateOf("")
        }

        Column {
            TextField(value = text, onValueChange = { text = it })
        }
    }
}

rememberSaveable must work because some components used it under the hood to restore scroll position and other things.

HiddenBottomSheetScreen crash

Declaring a TabNavigator before a BottomSheetNavigator leads to the crash below in version 1.0.0-beta10 but works just fine in 1.0.0-beta09.

TabNavigator(HomeTab) {
    BottomSheetNavigator {
        CurrentTab()
    }
}
java.lang.IllegalArgumentException: Key cafe.adriel.voyager.navigator.bottomSheet.HiddenBottomSheetScreen was used multiple times 
        at androidx.compose.runtime.saveable.SaveableStateHolderImpl$SaveableStateProvider$1$1.invoke(SaveableStateHolder.kt:89)
        at androidx.compose.runtime.saveable.SaveableStateHolderImpl$SaveableStateProvider$1$1.invoke(SaveableStateHolder.kt:88)
        at androidx.compose.runtime.DisposableEffectImpl.onRemembered(Effects.kt:81)
        at androidx.compose.runtime.CompositionImpl$RememberEventDispatcher.dispatchRememberObservers(Composition.kt:781)
        at androidx.compose.runtime.CompositionImpl.applyChanges(Composition.kt:639)
        at androidx.compose.runtime.Recomposer.composeInitial$runtime_release(Recomposer.kt:733)
        at androidx.compose.runtime.ComposerImpl$CompositionContextImpl.composeInitial$runtime_release(Composer.kt:2991)
        at androidx.compose.runtime.CompositionImpl.setContent(Composition.kt:433)
        at androidx.compose.ui.layout.SubcomposeLayoutState.subcomposeInto(SubcomposeLayout.kt:262)
        at androidx.compose.ui.layout.SubcomposeLayoutState.access$subcomposeInto(SubcomposeLayout.kt:148)
        at androidx.compose.ui.layout.SubcomposeLayoutState$subcompose$2.invoke(SubcomposeLayout.kt:237)
        at androidx.compose.ui.layout.SubcomposeLayoutState$subcompose$2.invoke(SubcomposeLayout.kt:234)
        at androidx.compose.runtime.snapshots.SnapshotStateObserver.withNoObservations(SnapshotStateObserver.kt:142)
        at androidx.compose.ui.node.OwnerSnapshotObserver.withNoSnapshotReadObservation$ui_release(OwnerSnapshotObserver.kt:55)
        at androidx.compose.ui.node.LayoutNode.withNoSnapshotReadObservation$ui_release(LayoutNode.kt:1122)
        at androidx.compose.ui.layout.SubcomposeLayoutState.subcompose(SubcomposeLayout.kt:234)
        at androidx.compose.ui.layout.SubcomposeLayoutState.subcompose(SubcomposeLayout.kt:229)
        at androidx.compose.ui.layout.SubcomposeLayoutState.subcompose$ui_release(SubcomposeLayout.kt:218)
        at androidx.compose.ui.layout.SubcomposeLayoutState$Scope.subcompose(SubcomposeLayout.kt:469)
        at androidx.compose.foundation.layout.BoxWithConstraintsKt$BoxWithConstraints$1$1.invoke-0kLqBqw(BoxWithConstraints.kt:66)
        at androidx.compose.foundation.layout.BoxWithConstraintsKt$BoxWithConstraints$1$1.invoke(BoxWithConstraints.kt:64)
        at androidx.compose.ui.layout.SubcomposeLayoutState$createMeasurePolicy$1.measure-3p2s80s(SubcomposeLayout.kt:348)
        at androidx.compose.ui.node.InnerPlaceable.measure-BRTryo0(InnerPlaceable.kt:50)
        at androidx.compose.ui.node.OuterMeasurablePlaceable$remeasure$3.invoke(OuterMeasurablePlaceable.kt:100)
        at androidx.compose.ui.node.OuterMeasurablePlaceable$remeasure$3.invoke(OuterMeasurablePlaceable.kt:99)
        at androidx.compose.runtime.snapshots.SnapshotStateObserver.observeReads(SnapshotStateObserver.kt:126)
        at androidx.compose.ui.node.OwnerSnapshotObserver.observeReads$ui_release(OwnerSnapshotObserver.kt:88)
        at androidx.compose.ui.node.OwnerSnapshotObserver.observeMeasureSnapshotReads$ui_release(OwnerSnapshotObserver.kt:76)
        at androidx.compose.ui.node.OuterMeasurablePlaceable.remeasure-BRTryo0(OuterMeasurablePlaceable.kt:99)
        at androidx.compose.ui.node.OuterMeasurablePlaceable.measure-BRTryo0(OuterMeasurablePlaceable.kt:71)
        at androidx.compose.ui.node.LayoutNode.measure-BRTryo0(LayoutNode.kt:1242)
        at androidx.compose.ui.layout.RootMeasurePolicy.measure-3p2s80s(RootMeasurePolicy.kt:38)
        at androidx.compose.ui.node.InnerPlaceable.measure-BRTryo0(InnerPlaceable.kt:50)
        at androidx.compose.ui.node.DelegatingLayoutNodeWrapper.measure-BRTryo0(DelegatingLayoutNodeWrapper.kt:118)
        at androidx.compose.ui.node.DelegatingLayoutNodeWrapper.measure-BRTryo0(DelegatingLayoutNodeWrapper.kt:118)
        at androidx.compose.ui.node.DelegatingLayoutNodeWrapper.measure-BRTryo0(DelegatingLayoutNodeWrapper.kt:118)
        at androidx.compose.ui.node.DelegatingLayoutNodeWrapper.measure-BRTryo0(DelegatingLayoutNodeWrapper.kt:118)

An easy way to fix this is simply by declaring the BottomSheetNavigator first, but that doesn't explain why this code is suddenly not working anymore.

BottomSheetNavigator {
    TabNavigator(PersonalTab) {
        CurrentTab()
    }
}

Question: Current library capabilities on android app

I'll already a little bit played around this library. And drew following navigation diagram of my expectations:
image

Maybe I'm not correctly described navigation flow or simple not understand jetpack compose (I'm working on it). And now I have several questions:

  1. How I can manage visibility of BottomNavigation when open concreate screen inside any tab? I can do it by passing callback, but it's hard to manage actual state with such approach. Also, theoretically, I can try to save each navigator of tab navigator and pass it to parent screen and then iterate over it?
  2. Why onBackPressed() not actually finishes app?
  3. Not a big problem but is there any way to close app using navigator?

Hilt integration issue

Hi,

Testing this library and there's a small issue with current hilt integration if we do not want to use ScreenModel or are just testing before switching to them.

If we just add the voyager-hilt dependency then we end up with a dagger issue

error: [Dagger/MissingBinding] java.util.Map<java.lang.Class<? extends cafe.adriel.voyager.hilt.ScreenModelFactory>,javax.inject.Provider<cafe.adriel.voyager.hilt.ScreenModelFactory>> cannot be provided without an @Provides-annotated method.
  public abstract static class SingletonC implements Application_GeneratedInjector,
                         ^
      java.util.Map<java.lang.Class<? extends cafe.adriel.voyager.hilt.ScreenModelFactory>,javax.inject.Provider<cafe.adriel.voyager.hilt.ScreenModelFactory>> is requested at
          cafe.adriel.voyager.hilt.ScreenModelEntryPoint.screenModelFactories()

This can be worked around by just creating fake ScreenModel / ScreenModelFactory and a module to bind them but this should not be necessary or pointed in the doc if there's a better way to fix.

I'm still not fluent with multibinding so maybe there's something else I miss.

How to multiple instance viewmodel for same compose fun

I have a list of items and a detail screen. Detail Screen is a compose function that takes a (post) parameter that I pass as an argument to the ViewModel.
val viewModel = getStateViewModel<PostDetailViewModel>(parameters = { parametersOf(args) })
The problem is that it looks like the viewModel is cached, and all the time it opens the first post (argument) that was followed.

In jetpack navigation works correctly.

Video.2021-08-17.11-34-03-1.mp4

Crash

Hi Mr Adriel,
Each time I add the dependencies to my project, I get the error below.
My compose version is 1.0.0-beta08 so I think it might be a versioning issue.

java.lang.NoSuchFieldError: No field None of type Landroidx/compose/ui/text/input/KeyboardCapitalization; in class Landroidx/compose/ui/text/input/KeyboardCapitalization; or its superclasses (declaration of 'androidx.compose.ui.text.input.KeyboardCapitalization' appears in /data/app/~~fNIyLfrseWUXElCjs4UbBQ==/com.example.sizingapplication-p97FFtKhLr3pGex5Onsc9w==/base.apk)
at androidx.compose.foundation.text.KeyboardOptions.(KeyboardOptions.kt:47)
at androidx.compose.foundation.text.KeyboardOptions.(KeyboardOptions.kt:56)
at com.example.sizingapplication.MainActivityKt$InputLayout$1.invoke(MainActivity.kt:132)
at com.example.sizingapplication.MainActivityKt$InputLayout$1.invoke(MainActivity.kt:117)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:116)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:34)
at androidx.compose.material.ScaffoldKt$ScaffoldLayout$1$1$1$bodyContentPlaceables$1.invoke(Scaffold.kt:316)
at androidx.compose.material.ScaffoldKt$ScaffoldLayout$1$1$1$bodyContentPlaceables$1.invoke(Scaffold.kt:314)
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.ui.layout.SubcomposeLayoutState$subcompose$2$1$1.invoke(SubcomposeLayout.kt:241)
at androidx.compose.ui.layout.SubcomposeLayoutState$subcompose$2$1$1.invoke(SubcomposeLayout.kt:241)
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.ComposerKt.invokeComposable(Composer.kt:3330)
at androidx.compose.runtime.ComposerImpl$doCompose$2$5.invoke(Composer.kt:2577)
at androidx.compose.runtime.ComposerImpl$doCompose$2$5.invoke(Composer.kt:2573)
at androidx.compose.runtime.SnapshotStateKt.observeDerivedStateRecalculations(SnapshotState.kt:540)
at androidx.compose.runtime.ComposerImpl.doCompose(Composer.kt:2566)
at androidx.compose.runtime.ComposerImpl.composeContent$runtime_release(Composer.kt:2517)
at androidx.compose.runtime.CompositionImpl.composeContent(Composition.kt:476)
at androidx.compose.runtime.Recomposer.composeInitial$runtime_release(Recomposer.kt:727)
at androidx.compose.runtime.ComposerImpl$CompositionContextImpl.composeInitial$runtime_release(Composer.kt:2980)
at androidx.compose.runtime.CompositionImpl.setContent(Composition.kt:432)
at androidx.compose.ui.layout.SubcomposeLayoutState.subcomposeInto(SubcomposeLayout.kt:259)
at androidx.compose.ui.layout.SubcomposeLayoutState.access$subcomposeInto(SubcomposeLayout.kt:145)
at androidx.compose.ui.layout.SubcomposeLayoutState$subcompose$2.invoke(SubcomposeLayout.kt:234)
at androidx.compose.ui.layout.SubcomposeLayoutState$subcompose$2.invoke(SubcomposeLayout.kt:231)
at androidx.compose.runtime.snapshots.SnapshotStateObserver.withNoObservations(SnapshotStateObserver.kt:144)
at androidx.compose.ui.node.OwnerSnapshotObserver.withNoSnapshotReadObservation$ui_release(OwnerSnapshotObserver.kt:49)
at androidx.compose.ui.node.LayoutNode.withNoSnapshotReadObservation$ui_release(LayoutNode.kt:1107)
at androidx.compose.ui.layout.SubcomposeLayoutState.subcompose(SubcomposeLayout.kt:231)
at androidx.compose.ui.layout.SubcomposeLayoutState.subcompose(SubcomposeLayout.kt:226)
at androidx.compose.ui.layout.SubcomposeLayoutState.subcompose$ui_release(SubcomposeLayout.kt:215)
at androidx.compose.ui.layout.SubcomposeLayoutState$Scope.subcompose(SubcomposeLayout.kt:466)
at androidx.compose.material.ScaffoldKt$ScaffoldLayout$1$1$1.invoke(Scaffold.kt:314)
at androidx.compose.material.ScaffoldKt$ScaffoldLayout$1$1$1.invoke(Scaffold.kt:241)
at androidx.compose.ui.layout.MeasureScope$layout$1.placeChildren(MeasureScope.kt:68)
2021-07-24 17:47:41.724 7238-7238/com.example.sizingapplication E/AndroidRuntime: at androidx.compose.ui.layout.SubcomposeLayoutState$createMeasurePolicy$1$measure$1.placeChildren(SubcomposeLayout.kt:357)
at androidx.compose.ui.node.LayoutNode$layoutChildren$1.invoke(LayoutNode.kt:925)
at androidx.compose.ui.node.LayoutNode$layoutChildren$1.invoke(LayoutNode.kt:915)
at androidx.compose.runtime.snapshots.SnapshotStateObserver.observeReads(SnapshotStateObserver.kt:128)
at androidx.compose.ui.node.OwnerSnapshotObserver.observeReads$ui_release(OwnerSnapshotObserver.kt:75)
at androidx.compose.ui.node.OwnerSnapshotObserver.observeLayoutSnapshotReads$ui_release(OwnerSnapshotObserver.kt:56)
at androidx.compose.ui.node.LayoutNode.layoutChildren$ui_release(LayoutNode.kt:915)
at androidx.compose.ui.node.LayoutNode.onNodePlaced$ui_release(LayoutNode.kt:901)
at androidx.compose.ui.node.InnerPlaceable.placeAt-f8xVGno(InnerPlaceable.kt:94)
at androidx.compose.ui.layout.Placeable.access$placeAt-f8xVGno(Placeable.kt:31)
at androidx.compose.ui.layout.Placeable$PlacementScope.place-70tqf50(Placeable.kt:370)
at androidx.compose.ui.node.OuterMeasurablePlaceable.placeAt-f8xVGno(OuterMeasurablePlaceable.kt:149)
at androidx.compose.ui.layout.Placeable.access$placeAt-f8xVGno(Placeable.kt:31)
at androidx.compose.ui.layout.Placeable$PlacementScope.place-70tqf50(Placeable.kt:370)
at androidx.compose.ui.layout.Placeable$PlacementScope.place-70tqf50$default(Placeable.kt:203)
at androidx.compose.foundation.layout.BoxKt.placeInBox(Box.kt:186)
at androidx.compose.foundation.layout.BoxKt.access$placeInBox(Box.kt:1)
at androidx.compose.foundation.layout.BoxKt$boxMeasurePolicy$1$measure$2.invoke(Box.kt:126)
at androidx.compose.foundation.layout.BoxKt$boxMeasurePolicy$1$measure$2.invoke(Box.kt:125)
at androidx.compose.ui.layout.MeasureScope$layout$1.placeChildren(MeasureScope.kt:68)
at androidx.compose.ui.node.LayoutNode$layoutChildren$1.invoke(LayoutNode.kt:925)
at androidx.compose.ui.node.LayoutNode$layoutChildren$1.invoke(LayoutNode.kt:915)
at androidx.compose.runtime.snapshots.SnapshotStateObserver.observeReads(SnapshotStateObserver.kt:128)
at androidx.compose.ui.node.OwnerSnapshotObserver.observeReads$ui_release(OwnerSnapshotObserver.kt:75)
at androidx.compose.ui.node.OwnerSnapshotObserver.observeLayoutSnapshotReads$ui_release(OwnerSnapshotObserver.kt:56)
at androidx.compose.ui.node.LayoutNode.layoutChildren$ui_release(LayoutNode.kt:915)
at androidx.compose.ui.node.LayoutNode.onNodePlaced$ui_release(LayoutNode.kt:901)
at androidx.compose.ui.node.InnerPlaceable.placeAt-f8xVGno(InnerPlaceable.kt:94)
at androidx.compose.ui.layout.Placeable.access$placeAt-f8xVGno(Placeable.kt:31)
at androidx.compose.ui.layout.Placeable$PlacementScope.place-70tqf50(Placeable.kt:370)
at androidx.compose.ui.layout.Placeable$PlacementScope.place-70tqf50$default(Placeable.kt:203)
at androidx.compose.ui.node.DelegatingLayoutNodeWrapper$measure$1$1.placeChildren(DelegatingLayoutNodeWrapper.kt:123)
at androidx.compose.ui.node.DelegatingLayoutNodeWrapper.placeAt-f8xVGno(DelegatingLayoutNodeWrapper.kt:111)
at androidx.compose.ui.layout.Placeable.access$placeAt-f8xVGno(Placeable.kt:31)
at androidx.compose.ui.layout.Placeable$PlacementScope.place-70tqf50(Placeable.kt:370)
at androidx.compose.ui.layout.Placeable$PlacementScope.place-70tqf50$default(Placeable.kt:203)
at androidx.compose.ui.node.DelegatingLayoutNodeWrapper$measure$1$1.placeChildren(DelegatingLayoutNodeWrapper.kt:123)
at androidx.compose.ui.node.DelegatingLayoutNodeWrapper.placeAt-f8xVGno(DelegatingLayoutNodeWrapper.kt:111)
at androidx.compose.ui.layout.Placeable.access$placeAt-f8xVGno(Placeable.kt:31)
at androidx.compose.ui.layout.Placeable$PlacementScope.placeWithLayer(Placeable.kt:393)
at androidx.compose.ui.layout.Placeable$PlacementScope.placeWithLayer$default(Placeable.kt:266)
at androidx.compose.ui.graphics.SimpleGraphicsLayerModifier$measure$1.invoke(GraphicsLayerModifier.kt:221)
2021-07-24 17:47:41.730 7238-7238/com.example.sizingapplication E/AndroidRuntime: at androidx.compose.ui.graphics.SimpleGraphicsLayerModifier$measure$1.invoke(GraphicsLayerModifier.kt:220)
at androidx.compose.ui.layout.MeasureScope$layout$1.placeChildren(MeasureScope.kt:68)
at androidx.compose.ui.node.DelegatingLayoutNodeWrapper.placeAt-f8xVGno(DelegatingLayoutNodeWrapper.kt:111)
at androidx.compose.ui.layout.Placeable.access$placeAt-f8xVGno(Placeable.kt:31)
at androidx.compose.ui.layout.Placeable$PlacementScope.place-70tqf50(Placeable.kt:370)
at androidx.compose.ui.layout.Placeable$PlacementScope.place-70tqf50$default(Placeable.kt:203)
at androidx.compose.ui.node.DelegatingLayoutNodeWrapper$measure$1$1.placeChildren(DelegatingLayoutNodeWrapper.kt:123)
at androidx.compose.ui.node.DelegatingLayoutNodeWrapper.placeAt-f8xVGno(DelegatingLayoutNodeWrapper.kt:111)
at androidx.compose.ui.layout.Placeable.access$placeAt-f8xVGno(Placeable.kt:31)
at androidx.compose.ui.layout.Placeable$PlacementScope.placeRelative(Placeable.kt:359)
at androidx.compose.ui.layout.Placeable$PlacementScope.placeRelative$default(Placeable.kt:179)
at androidx.compose.foundation.layout.FillModifier$measure$1.invoke(Size.kt:632)
at androidx.compose.foundation.layout.FillModifier$measure$1.invoke(Size.kt:631)
at androidx.compose.ui.layout.MeasureScope$layout$1.placeChildren(MeasureScope.kt:68)
at androidx.compose.ui.node.DelegatingLayoutNodeWrapper.placeAt-f8xVGno(DelegatingLayoutNodeWrapper.kt:111)
at androidx.compose.ui.layout.Placeable.access$placeAt-f8xVGno(Placeable.kt:31)
at androidx.compose.ui.layout.Placeable$PlacementScope.placeWithLayer-aW-9-wM(Placeable.kt:396)
at androidx.compose.ui.node.OuterMeasurablePlaceable.placeAt-f8xVGno(OuterMeasurablePlaceable.kt:151)
at androidx.compose.ui.layout.Placeable.access$placeAt-f8xVGno(Placeable.kt:31)
at androidx.compose.ui.layout.Placeable$PlacementScope.placeRelativeWithLayer(Placeable.kt:385)
at androidx.compose.ui.layout.Placeable$PlacementScope.placeRelativeWithLayer$default(Placeable.kt:246)
at androidx.compose.ui.layout.RootMeasurePolicy$measure$2.invoke(RootMeasurePolicy.kt:43)
at androidx.compose.ui.layout.RootMeasurePolicy$measure$2.invoke(RootMeasurePolicy.kt:42)
at androidx.compose.ui.layout.MeasureScope$layout$1.placeChildren(MeasureScope.kt:68)
at androidx.compose.ui.node.LayoutNode$layoutChildren$1.invoke(LayoutNode.kt:925)
at androidx.compose.ui.node.LayoutNode$layoutChildren$1.invoke(LayoutNode.kt:915)
at androidx.compose.runtime.snapshots.Snapshot$Companion.observe(Snapshot.kt:1776)
at androidx.compose.runtime.snapshots.SnapshotStateObserver.observeReads(SnapshotStateObserver.kt:123)
at androidx.compose.ui.node.OwnerSnapshotObserver.observeReads$ui_release(OwnerSnapshotObserver.kt:75)
at androidx.compose.ui.node.OwnerSnapshotObserver.observeLayoutSnapshotReads$ui_release(OwnerSnapshotObserver.kt:56)
at androidx.compose.ui.node.LayoutNode.layoutChildren$ui_release(LayoutNode.kt:915)
at androidx.compose.ui.node.LayoutNode.onNodePlaced$ui_release(LayoutNode.kt:901)
at androidx.compose.ui.node.InnerPlaceable.placeAt-f8xVGno(InnerPlaceable.kt:94)
at androidx.compose.ui.layout.Placeable.access$placeAt-f8xVGno(Placeable.kt:31)
at androidx.compose.ui.layout.Placeable$PlacementScope.place-70tqf50(Placeable.kt:370)
at androidx.compose.ui.layout.Placeable$PlacementScope.place-70tqf50$default(Placeable.kt:203)
at androidx.compose.ui.node.DelegatingLayoutNodeWrapper$measure$1$1.placeChildren(DelegatingLayoutNodeWrapper.kt:123)
at androidx.compose.ui.node.DelegatingLayoutNodeWrapper.placeAt-f8xVGno(DelegatingLayoutNodeWrapper.kt:111)
at androidx.compose.ui.layout.Placeable.access$placeAt-f8xVGno(Placeable.kt:31)
at androidx.compose.ui.layout.Placeable$PlacementScope.place-70tqf50(Placeable.kt:370)
at androidx.compose.ui.layout.Placeable$PlacementScope.place-70tqf50$default(Placeable.kt:203)
at androidx.compose.ui.node.DelegatingLayoutNodeWrapper$measure$1$1.placeChildren(DelegatingLayoutNodeWrapper.kt:123)
2021-07-24 17:47:41.733 7238-7238/com.example.sizingapplication E/AndroidRuntime: at androidx.compose.ui.node.DelegatingLayoutNodeWrapper.placeAt-f8xVGno(DelegatingLayoutNodeWrapper.kt:111)
at androidx.compose.ui.layout.Placeable.access$placeAt-f8xVGno(Placeable.kt:31)
at androidx.compose.ui.layout.Placeable$PlacementScope.place-70tqf50(Placeable.kt:370)
at androidx.compose.ui.layout.Placeable$PlacementScope.place-70tqf50$default(Placeable.kt:203)
at androidx.compose.ui.node.DelegatingLayoutNodeWrapper$measure$1$1.placeChildren(DelegatingLayoutNodeWrapper.kt:123)
at androidx.compose.ui.node.DelegatingLayoutNodeWrapper.placeAt-f8xVGno(DelegatingLayoutNodeWrapper.kt:111)
at androidx.compose.ui.layout.Placeable.access$placeAt-f8xVGno(Placeable.kt:31)
at androidx.compose.ui.layout.Placeable$PlacementScope.place-70tqf50(Placeable.kt:370)
at androidx.compose.ui.node.OuterMeasurablePlaceable.placeAt-f8xVGno(OuterMeasurablePlaceable.kt:149)
at androidx.compose.ui.layout.Placeable.access$placeAt-f8xVGno(Placeable.kt:31)
at androidx.compose.ui.layout.Placeable$PlacementScope.placeRelative(Placeable.kt:359)
at androidx.compose.ui.layout.Placeable$PlacementScope.placeRelative$default(Placeable.kt:179)
at androidx.compose.ui.node.LayoutNode.place$ui_release(LayoutNode.kt:803)
at androidx.compose.ui.node.MeasureAndLayoutDelegate.measureAndLayout(MeasureAndLayoutDelegate.kt:213)
at androidx.compose.ui.platform.AndroidComposeView.onMeasure(AndroidComposeView.android.kt:547)
at android.view.View.measure(View.java:25466)
at androidx.compose.ui.platform.AbstractComposeView.internalOnMeasure$ui_release(ComposeView.android.kt:278)
at androidx.compose.ui.platform.AbstractComposeView.onMeasure(ComposeView.android.kt:265)
at android.view.View.measure(View.java:25466)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6957)
at android.widget.FrameLayout.onMeasure(FrameLayout.java:194)
at android.view.View.measure(View.java:25466)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6957)
at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1552)
at android.widget.LinearLayout.measureVertical(LinearLayout.java:842)
at android.widget.LinearLayout.onMeasure(LinearLayout.java:721)
at android.view.View.measure(View.java:25466)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6957)
at android.widget.FrameLayout.onMeasure(FrameLayout.java:194)
at com.android.internal.policy.DecorView.onMeasure(DecorView.java:747)
at android.view.View.measure(View.java:25466)
at android.view.ViewRootImpl.performMeasure(ViewRootImpl.java:3397)
at android.view.ViewRootImpl.measureHierarchy(ViewRootImpl.java:2228)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2486)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1952)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:8171)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:972)
at android.view.Choreographer.doCallbacks(Choreographer.java:796)
at android.view.Choreographer.doFrame(Choreographer.java:731)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:957)
at android.os.Handler.handleCallback(Handler.java:938)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:223)
at android.app.ActivityThread.main(ActivityThread.java:7656)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)

Multiplatform seems to break Android builds.

> Could not resolve all artifacts for configuration ':modules:ui-bottomsheet-displayconfiguration:debugRuntimeClasspath'.
   > Could not find org.jetbrains.compose.runtime:runtime:1.0.1-rc2.
     Required by:
         project :modules:ui-bottomsheet-displayconfiguration > cafe.adriel.voyager:voyager-core:1.0.0-beta14 > cafe.adriel.voyager:voyager-core-android-debug:1.0.0-beta14
         project :modules:ui-bottomsheet-displayconfiguration > cafe.adriel.voyager:voyager-navigator:1.0.0-beta14 > cafe.adriel.voyager:voyager-navigator-android-debug:1.0.0-beta14
   > Could not find org.jetbrains.compose.ui:ui:1.0.1-rc2.
     Required by:
         project :modules:ui-bottomsheet-displayconfiguration > cafe.adriel.voyager:voyager-core:1.0.0-beta14 > cafe.adriel.voyager:voyager-core-android-debug:1.0.0-beta14
         project :modules:ui-bottomsheet-displayconfiguration > cafe.adriel.voyager:voyager-navigator:1.0.0-beta14 > cafe.adriel.voyager:voyager-navigator-android-debug:1.0.0-beta14

Is there a new way to handle the deps? I do not want jetbrain compose in the android app.

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.