Ilya Gazman
Ilya Gazman

Reputation: 32271

How to make a dynamic start destination in the Android Jetpack Navigation

I am building an SMS app, using the Navigation pack from Android Jetpack to navigate between screens.

When users open my app for the first time, they land on a permissions screen where they need to grand default app permissions and some regular permissions before they can move into the main screen.

I also need to show the permissions screen when the user changes their default SMS app and then reopen my app.

I saw the Conditional Navigation section in Android Navigations docs. It suggests placing this logic in the main screen fragment onViewCreated method. But I am afraid that it will impact the startup time of my app.

Is there a more efficient way to implement this? Ideally, I would like to handle this logic in the activity.

Upvotes: 15

Views: 13682

Answers (2)

Petr Kubáč
Petr Kubáč

Reputation: 1640

You can set startDestination of the graph programatically like this

val graph = findNavController(R.id.YOUR_CONTAINER_ID).graph
graph.startDestination = R.id.ID_OF_THE_FRAGMENT_FOR_START_DESTINATION
findNavController(R.id.YOUR_CONTAINER_ID).setGraph(graph)

This can be executed in your Activity's onCreate() method

Upvotes: 8

Xid
Xid

Reputation: 4961

Don't set the navigation graph in the XML file.

<?xml version="1.0" encoding="utf-8"?>
<androidx.fragment.app.FragmentContainerView 
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/navigationHostFragmentMain"
    android:name="androidx.navigation.fragment.NavHostFragment"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:defaultNavHost="true" />

In your Activity you can set the start destination programmatically and then set the navigation graph.

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

    setNavigationGraph()
}

private fun setNavigationGraph() {
    val navHostFragment =
        supportFragmentManager.findFragmentById(R.id.navigationHostFragmentMain) as NavHostFragment
    val navController = navHostFragment.navController

    val navGraph = navController.navInflater.inflate(R.navigation.navigation_graph)
    navGraph.startDestination =
        if (viewModel.isLoggedIn) {
            R.id.homeFragment
        } else {
            R.id.loginFragment
        }

    navController.graph = navGraph
}

Upvotes: 27

Related Questions