Search code examples
androiddependency-injectiondagger-2android-architecture-componentsandroidx

Is it possible to use DI with the androidx.navigation.NavController


So, the title of this reflects the question. to obtain a link on a navigation controller (androidx.navigation.NavController) usually we use following code:

NavController navController = Navigation.findNavController(this, R.id.nav_host_frag);

Is it possible to inject a NavController using Dagger2 framework? (findNavController requires an activity or a view reference) Maybe it's a silly question and nobody injects the androidx.navigation.NavController, but nevertheless I decided to ask this question to be certain in my assumptions. Thanks ahead


Solution

  • I don't see why you would want to inject the NavController when there are methods for you to find it, also I would be concerned with using dependency injection due to holding a reference to an Activity.

    Given you are working with an Activity you would normally find the controller by using the following method:

    private val navController: NavController by lazy { findNavController(R.id.main_container) }
    

    Now if we take a look at the source code for the method findNavController() you will notice that it uses an extension function and Navigation.findNavController(this, viewId).

    /**
     * Find a [NavController] given the id of a View and its containing
     * [Activity].
     *
     * Calling this on a View that is not a [NavHost] or within a [NavHost]
     * will result in an [IllegalStateException]
     */
    fun Activity.findNavController(@IdRes viewId: Int): NavController =
            Navigation.findNavController(this, viewId)
    

    The only thing I would do to complement the above is to create another extension function to facilitate navigation from a Fragment.

    fun Fragment.navigate(resId: Int, bundle: Bundle? = null) {
        NavHostFragment.findNavController(this).navigate(resId, bundle)
    }
    

    Then you could simply use within a Fragment:

    navigate(
        R.id.action_fragmentA_to_FragmentB,
        bundleOf(Global.CAN_NAVIGATE_BACK to false)
    )