Android Navigation Advanced Sample Dependency Injection (Hilt) on config changes issue

1.1k views Asked by At

having a problem with Navigation Advanced Sample provided by Google developers. Main problem is that in regular case senario for Hilt dependency injection we can simply:

  1. Create Custom FragmentFactory
  2. Create Custom NavHostFragment
  3. Asigne it to FragmentContainerView by using android:name="com.package.CustomNavHostFragment"

But how I can do it by using this Navigation Advanced Sample ?

Because now on Activity recreate I'm getting typical HILT error at package.MainActivity.onCreate(MainActivity.kt:23)

EDIT:

More about the problem. By this provided simple we should use NavigationExtension.kt and setup everything by using BottomNavigationView.setupWithNavController

And problem is that we need to use the default NavHostFragment in order to create a container for each navigation graph. Is it possible somehow to use custom NavHostFragment? If yes, how can I overite that NavHostFragment.onCreate() mechanism? I'm talking about this line in NavigationExtension.kt class

1

There are 1 answers

0
Andrew On

If I understood your problem correctly, you want to create a custom NavHostFragment? Yes, that is possible but you don't need to overwrite NavHostFragment.onCreate(). Create a custom NavHostFragment with the following steps: First, create a MainFragmentFactory

MainFragmentFactory

class MainFragmentFactory @Inject constructor(
    //... your dependencies
) : FragmentFactory() {
    override fun instantiate(classLoader: ClassLoader, className: String): Fragment = when(className) {
        MyFragment::class.java.name -> MyFragment(//.. your dependencies)
        MySecondFragment::class.java.name -> MySecondFragment(/...)
        // other fragments

        else -> super.instantiate(classLoader, className)
    }
}

Then you need to attach your fragmentFractory to your custom MainNavHostFragment

MainNavHostFragment

@AndroidEntryPoint
class MainNavHostFragment : NavHostFragment() {

    @Inject
    lateinit var mainFragmentFactory: MainFragmentFactory

    override fun onAttach(context: Context) {
        super.onAttach(context)
        childFragmentManager.fragmentFactory = mainFragmentFactory
    }
}

Now you need to add your custom NavHostFragment to your activity_main.xml

Activity_main.xml

<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".framework.ui.view.MainActivity">

    <fragment
        android:id="@+id/fragment_container"
        <!-- Add path to your custom NavHostFragment here -->
        android:name="com.example.app.framework.ui.view.utils.MainNavHostFragment"
        android:layout_width="match_parent"
        android:layout_height="@dimen/wrapContent"
        app:defaultNavHost="true"
        app:layout_constraintBottom_toTopOf="@+id/bottomNavigationView"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        <!-- Your NavGraph -->
        app:navGraph="@navigation/nav_main" />

    <com.google.android.material.bottomnavigation.BottomNavigationView
        android:id="@+id/bottomNavigationView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:itemHorizontalTranslationEnabled="false"
        app:labelVisibilityMode="labeled"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:menu="@menu/bottom_nav_menu_logged_out" />
</androidx.constraintlayout.widget.ConstraintLayout>

Dagger-Hilt will now create all your fragments and instantiate it.