Search code examples
androidandroid-studioandroid-project-template

Why doesn't Navigation Drawer project template (Studio 3.6.1) load correct controller on Android Nougat?


Problem Background

I have simply chosen the Navigation Drawer Template from the project templates (see highlighted item in image), built the app and run it on the emulator (Android Nougat (v7) API 24).

navigation drawer project template

The Problem

When I open the menu and select another item it does not load the new item (new fragment via the controller).

More Details of Problem

  1. The app starts here...(home fragment - first image).
  2. I click the gallery menu item (2nd image) and the home fragment still displays (see first image).

home fragment click gallery menu item

What I've Tried

I've run this same project on another emulator running Android Pie and it works as expected -- When I click the gallery menu item the gallery fragment loads and I see "This is Gallery fragment".

Other Things I've Tried

I've also opened up logcat and then clicked the menu item but there is nothing shown, even when I have all filters turned off.

Relevant Template Code

The template code in the MainActivity (which loads the fragments and controllers, initializes everything) in onCreate looks like:

override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        val toolbar: Toolbar = findViewById(R.id.toolbar)
        setSupportActionBar(toolbar)

        val fab: FloatingActionButton = findViewById(R.id.fab)
        fab.setOnClickListener { view ->
            Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
                    .setAction("Action", null).show()
        }

 // ###########################################################
 // #### MY NOTES -- This is the relevant code ################

        val drawerLayout: DrawerLayout = findViewById(R.id.drawer_layout)
        val navView: NavigationView = findViewById(R.id.nav_view)
        val navController = findNavController(R.id.nav_host_fragment)
        // Passing each menu ID as a set of Ids because each
        // menu should be considered as top level destinations.
        appBarConfiguration = AppBarConfiguration(setOf(
                R.id.nav_home, R.id.nav_gallery, R.id.nav_slideshow), drawerLayout)
        setupActionBarWithNavController(navController, appBarConfiguration)
        navView.setupWithNavController(navController)
    }

What / Where Can I Log To Determine What Is Happening?

Can you tell me why this is occurring?
Or, can you provide me with an idea where I can put some logging statements to determine what is firing so I can tell what is failing?

Update - Additional Info

There is definitely something incorrect with the template because the mobile_navigation.xml references a class that doesn't even exist in the project:

mobile_navigation.xml

Even though the app.actionmobile.navdraw.ui.home.HomeSecondFragment does not exist in this project, the app still builds and runs. Hmm.... Not sure how that is possible.

FYI - That was added by the project template, not me.

Other Thing I Tried I set the altered the top of the mobile_navigation.xml from:

app:startDestination="@+id/nav_home"

to

 app:startDestination="@+id/nav_gallery"

Tested to see if the gallery fragment would load as the first fragment and it did with no problems.

Restating Issue

Again the issue I have is that the selection of the menu item does not load the new fragment on Nougat, but does on Pie. Not sure how a platform fixes this???


Solution

  • I was finally able to fix this.

    Old Dependencies In Template Project

    First of all I had to update a bunch of packages that were out of date (which were added by the default project template).

    Here are the diffs on the dependencies. Of course, the red ones are the old ones and the green are the new ones:

    diffs of dependencies

    The Odd Thing

    However, the odd thing is that when you update those dependencies you'll get a warning that modelView class is deprecated. It looks like this in Studio (in every one of the Fragments -- all defined by the project Template:

    viewModelProvider deprecated

    I Googled this issue and discovered that the code needs to be altered so it uses:

    import androidx.lifecycle.ViewModelProvider
    

    Notice it is singular (versus the old which was ViewModelProviders)...a bit tricky.

    You also have to change every one of the Fragments where they reference this to build the viewModel so the code looks like:

    galleryViewModel =
                    ViewModelProvider.AndroidViewModelFactory.getInstance(Application())
                        .create(GalleryViewModel::class.java)
    

    Once you make those changes and rebuild, the app will not have any deprecated calls and the menu items work on my Nougat image also.

    Success!

    It is still quite odd that it behaved differently on different versions of the OS. But, that is probably to be expected for undefined behavior.