17

I just got my code to compile and when I try to start the app I receive the error. I'm currently trying to setup RecycleView for my class project. My goal is to make the RecycleView show content sorta like the reddit mobile app. I thought my RecycleView named "scrollview1" had a navcontroller setup. Not sure why I'm getting this output

java.lang.RuntimeException: Unable to start activity ComponentInfo{com.john.chanapi/com.john.chanapi.MainActivity}: java.lang.IllegalStateException: Activity com.john.chanapi.MainActivity@1850938 does not have a NavController set on 2131230866

My MainActivity.kt:

package com.john.chanapi

import android.os.Bundle
import com.google.android.material.floatingactionbutton.FloatingActionButton
import com.google.android.material.snackbar.Snackbar
import androidx.navigation.findNavController
import androidx.navigation.ui.AppBarConfiguration
import androidx.navigation.ui.navigateUp
import androidx.navigation.ui.setupActionBarWithNavController
import androidx.navigation.ui.setupWithNavController
import androidx.drawerlayout.widget.DrawerLayout
import com.google.android.material.navigation.NavigationView
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.Toolbar
import android.view.Menu
import android.view.View

class MainActivity : AppCompatActivity() {

    private lateinit var appBarConfiguration: AppBarConfiguration

    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()
        }
        val drawerLayout: DrawerLayout = findViewById(R.id.drawer_layout)
        val navView: NavigationView = findViewById(R.id.nav_view)
        val navController = findNavController(R.id.scrollview1)
        // 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_new, R.id.nav_rising,
                R.id.nav_top, R.id.nav_inbox, R.id.nav_message
            ), drawerLayout
        )
        setupActionBarWithNavController(navController, appBarConfiguration)
        navView.setupWithNavController(navController)
    }


    override fun onCreateOptionsMenu(menu: Menu): Boolean {
        // Inflate the menu; this adds items to the action bar if it is present.
        menuInflater.inflate(R.menu.main, menu)
        return true
    }

    override fun onSupportNavigateUp(): Boolean {
        val navController = findNavController(R.id.scrollview1)
        return navController.navigateUp(appBarConfiguration) || super.onSupportNavigateUp()
    }
}

My activity_main.xml:

<?xml version="1.0" encoding="utf-8"?>
<androidx.drawerlayout.widget.DrawerLayout 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:id="@+id/drawer_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"
    tools:openDrawer="start">

    <include
        layout="@layout/app_bar_main"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

    <com.google.android.material.navigation.NavigationView
        android:id="@+id/nav_view"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:fitsSystemWindows="true"
        app:headerLayout="@layout/nav_header_main"
        app:menu="@menu/activity_main_drawer" />

</androidx.drawerlayout.widget.DrawerLayout>
sgtvance
  • 173
  • 1
  • 1
  • 7

3 Answers3

29

To be on the safer side, (within an Activity) avoid using findNavController(Int) to initialize a NavController instead initialize it from NavHostFragment as shown

val navHostFragment =
            supportFragmentManager.findFragmentById(R.id.navigation_host) as NavHostFragment
val navController: NavController = navHostFragment.navController
Mitch
  • 942
  • 12
  • 16
0

val navController = findNavController(R.id.scrollview1)

because R.id.scrollview1 will find the UI component that is RecyclerView,

not NavController

GuanHongHuang
  • 879
  • 3
  • 12
0

Inside onCreate views are not inflated yet. When you call findNavController it will fail.

One solution is to override the onViewCreated method and move the code after setSupportActionBar into onViewCreated.

Sample

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

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    val fab: FloatingActionButton = findViewById(R.id.fab)
    fab.setOnClickListener {}

    val drawerLayout: DrawerLayout = findViewById(R.id.drawer_layout)
    val navView: NavigationView = findViewById(R.id.nav_view)
    val navController = findNavController(R.id.scrollview1)
    // 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_new, R.id.nav_rising,
            R.id.nav_top, R.id.nav_inbox, R.id.nav_message
        ), drawerLayout
    )
    setupActionBarWithNavController(navController, appBarConfiguration)
    navView.setupWithNavController(navController)
}
Yang Liu
  • 905
  • 6
  • 14