1

I'm initialising a graph in Activity using Kotlin DSL and using navGraphViewModels() to acquire an instance of vm in the onCreate() of the fragment. However after process death the app crashes

Caused by: java.lang.IllegalArgumentException: No destination with route main_navigation is on the NavController's back stack. The current destination is null

MainActivity.kt

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        val navController = (supportFragmentManager
            .findFragmentById(R.id.nav_host_fragment) as NavHostFragment).navController
        
        val graph = navController.createGraph(
            startDestination = "MyFragment1", route = "main_navigation"
        ) {
            fragment<MyFragment1>("MyFragment1") {
                deepLink("fi://fragment1")
                argument("testing") {
                    type = NavType.StringType
                    defaultValue = "hello"
                }
            }

            navigation("MyFragment2", "included_graph") {
                fragment<MyFragment2>("MyFragment2") {
                    deepLink("fi://fragment2")
                    argument("testing") {
                        type = NavType.StringType
                        nullable = true
                    }
                }
            }
        }

        navController.graph = graph
    }

MyFragment1.kt

    private val vm: Vm by navGraphViewModels("main_navigation")

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

Stacktrace

                 Caused by: java.lang.IllegalArgumentException: No destination with route main_navigation is on the NavController's back stack. The current destination is null
                    at androidx.navigation.NavController.getBackStackEntry(NavController.kt:2472)
                    at com.example.testingnavigation.MyFragment1$special$$inlined$navGraphViewModels$default$1.invoke(NavGraphViewModelLazy.kt:209)
                    at com.example.testingnavigation.MyFragment1$special$$inlined$navGraphViewModels$default$1.invoke(NavGraphViewModelLazy.kt:208)
                    at kotlin.SynchronizedLazyImpl.getValue(LazyJVM.kt:74)
                    at androidx.navigation.NavGraphViewModelLazyKt.navGraphViewModels$lambda-3(NavGraphViewModelLazy.kt:208)
                    at androidx.navigation.NavGraphViewModelLazyKt.access$navGraphViewModels$lambda-3(NavGraphViewModelLazy.kt:1)
                    at com.example.testingnavigation.MyFragment1$special$$inlined$navGraphViewModels$default$4.invoke(NavGraphViewModelLazy.kt:217)
                    at com.example.testingnavigation.MyFragment1$special$$inlined$navGraphViewModels$default$4.invoke(NavGraphViewModelLazy.kt:214)
                    at androidx.lifecycle.ViewModelLazy.getValue(ViewModelLazy.kt:47)
                    at androidx.lifecycle.ViewModelLazy.getValue(ViewModelLazy.kt:35)
                    at com.example.testingnavigation.MyFragment1.getVm(MyFragment1.kt:26)
                    at com.example.testingnavigation.MyFragment1.onCreate(MyFragment1.kt:30)
                    at androidx.fragment.app.Fragment.performCreate(Fragment.java:3094)
                    at androidx.fragment.app.FragmentStateManager.create(FragmentStateManager.java:504)
                    at androidx.fragment.app.FragmentStateManager.moveToExpectedState(FragmentStateManager.java:268)
                    at androidx.fragment.app.FragmentStore.moveToExpectedState(FragmentStore.java:122)
                    at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1455)
                    at androidx.fragment.app.FragmentManager.dispatchStateChange(FragmentManager.java:3034)
                    at androidx.fragment.app.FragmentManager.dispatchCreate(FragmentManager.java:2941)
                    at androidx.fragment.app.Fragment.restoreChildFragmentState(Fragment.java:1989)
                    at androidx.fragment.app.Fragment.onCreate(Fragment.java:1967)
                    at androidx.navigation.fragment.NavHostFragment.onCreate(NavHostFragment.kt:163)
                    at androidx.fragment.app.Fragment.performCreate(Fragment.java:3094)
                    at androidx.fragment.app.FragmentStateManager.create(FragmentStateManager.java:504)
                    at androidx.fragment.app.FragmentStateManager.moveToExpectedState(FragmentStateManager.java:268)
                    at androidx.fragment.app.FragmentStore.moveToExpectedState(FragmentStore.java:114)
                    at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1455)
                    at androidx.fragment.app.FragmentManager.dispatchStateChange(FragmentManager.java:3034)
                    at androidx.fragment.app.FragmentManager.dispatchCreate(FragmentManager.java:2941)
14:03:56.302  E     at androidx.fragment.app.FragmentController.dispatchCreate(FragmentController.java:252)
                    at androidx.fragment.app.FragmentActivity.onCreate(FragmentActivity.java:219)
                    at com.example.testingnavigation.MainActivity.onCreate(MainActivity.kt:17)
                    at android.app.Activity.performCreate(Activity.java:8119)
                    at android.app.Activity.performCreate(Activity.java:8103)
                    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1359)
                    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3713)
                    ... 11 more

Steps to reproduce the crash

  • Open app and put the app to background
  • then use this command adb shell am kill <package_name>
  • relaunch app from app icon.

It doesn't crash when directly setting the navgraph in the activity_main.xml layout file.

Whats the right way to use the navigation via kotlin DSL?

5
  • 2
    As seen in the stack trace, onCreate for Fragments run before the rest of your code in onCreate of your activity. What is viewModel.someFunction() and why is it in onCreate()? Why isn't it in the init block of your ViewModel or in onViewCreated? Commented Apr 1, 2024 at 11:41
  • Its a sample code, thus I added a dummy reference to VM. In the actual implementation I would have the VM implement DefaultLifecycleObserver and make an API call in onCreate(). Also, register the VM as lifecycle observer in the fragment's onCreate. Commented Apr 1, 2024 at 12:47
  • Those would suffer the same problem - the Fragment will also trigger a LifecycleObserver at the same time as onCreate, which is still too early. If you have an actual concrete example, that would be helpful in pointing to what you should actually be doing. Commented Apr 1, 2024 at 15:22
  • Thanks @ianhanniballake for the prompt response. Like I was mentioning earlier, I could be doing many different thing in the onCreate(). But in this case, lets say I'm making an API call which is meant to load the content of the screen. Also, whats the general recommendation of usage of navgraph scoped view model when using kotlin dsl nav graph? Commented Apr 2, 2024 at 8:06
  • @ianhanniballake any input? Commented Apr 3, 2024 at 16:05

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.