首页 > 解决方案 > IllegalStateException: Activity 没有设置 NavController

问题描述

我尝试编写一个 Android 应用程序,它使用来自 androidx 的导航组件、工具栏和抽屉布局从左侧滑入设置菜单。我按照指南开始使用 Navigation 组件并尝试使用本指南使用 NavigationUI 更新 UI 组件来添加顶部应用栏和设置。

当我的应用程序启动时,会引发以下异常:

java.lang.IllegalStateException: Activity ....MainActivity@e686cd8 does not have a NavController set on 2131230993

旁注:如果我nav_graph.xml在设计模式下打开,主机窗格会报告“未找到 NavHostFragments。此导航图必须从布局中的 NavHostFragment 引用才能访问。” 也许这个错误和异常是相关的并且共享相同的根本原因。但是,我的导航图被 aNavHostFragment虽然引用,见下文。

活动主.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:context=".MainActivity">

  <LinearLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <androidx.appcompat.widget.Toolbar
        android:id="@+id/main_toolbar"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:background="?attr/colorPrimary"
        android:theme="?attr/actionBarTheme" />

    <androidx.fragment.app.FragmentContainerView
        android:id="@+id/nav_host_fragment"
        android:name="androidx.navigation.fragment.NavHostFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:defaultNavHost="true"
        app:navGraph="@navigation/nav_graph" />
  </LinearLayout>

  <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:menu="@menu/drawer_view"
    app:headerLayout="@layout/nav_header" />
</androidx.drawerlayout.widget.DrawerLayout>

这种布局

nav_header.xml:

<?xml version="1.0" encoding="utf-8"?>
<android.widget.LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="match_parent"
  android:layout_height="192dp"
  android:background="?attr/colorPrimaryDark"
  android:gravity="bottom"
  android:padding="16dp"
  android:theme="@style/ThemeOverlay.AppCompat.Dark">

  <TextView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="@string/app_name"
    android:textAppearance="@style/TextAppearance.AppCompat.Body1" />
</android.widget.LinearLayout>

抽屉视图.xml:

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
  <group android:checkableBehavior="single">
    <item
      android:id="@+id/nav_home"
      android:icon="@drawable/ic_home"
      android:title="@string/home"/>
    <item
      android:id="@+id/nav_settings"
      android:icon="@drawable/ic_settings"
      android:title="@string/settings" />
  </group>
</menu>

片段主页.xml:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:tools="http://schemas.android.com/tools"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  tools:context=".HomeFragment"/>

该片段被nav_graph(粘贴在下面)作为主片段(起始目的地)引用。

nav_graph.xml:

<?xml version="1.0" encoding="utf-8"?>
<navigation 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/nav_graph"
  app:startDestination="@id/homeFragment">

  <fragment
    android:id="@+id/homeFragment"
    android:name="de.mhnnet.lychee4android.HomeFragment"
    android:label="fragment_home"
    tools:layout="@layout/fragment_home" />
</navigation>

MainActivity.java:

protected void onCreate( Bundle savedInstanceState ) {
  super.onCreate( savedInstanceState );
  setContentView( R.layout.activity_main );

  NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment );
  AppBarConfiguration appBarConfiguration =
    new AppBarConfiguration.Builder(navController.getGraph()).build();
  Toolbar toolbar = findViewById( R.id.main_toolbar );
  NavigationUI.setupWithNavController( toolbar, navController, appBarConfiguration );
}

进一步说明:

我已经找到了一些提示androidx.fragment.app.FragmentContainerView应该替换为fragment. 但是,这感觉不对,因为 linter 建议使用FragmentContainerView而不是fragment官方Android 文档也使用FragmentContainerView

标签: androidandroid-fragmentsnavigation-drawerandroid-architecture-componentsandroid-architecture-navigation

解决方案


可以Nav Controller参加您的活动,或者更换您的

    <androidx.fragment.app.FragmentContainerView
        android:id="@+id/nav_host_fragment"
        android:name="androidx.navigation.fragment.NavHostFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:defaultNavHost="true"
        app:navGraph="@navigation/nav_graph" />

    <fragment
        android:id="@+id/nav_host_fragment"
        android:name="androidx.navigation.fragment.NavHostFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:defaultNavHost="true"
        app:navGraph="@navigation/nav_graph" />

FragmentContainerView但正如 lint 建议使用以下代码更改片段以进入Nav Controller您的活动。


        NavHostFragment navHostFragment = (NavHostFragment) getSupportFragmentManager().findFragmentById(R.id.nav_host_fragment);

        if (navHostFragment != null) {

            NavController navController = navHostFragment.getNavController();

            // Setup NavigationUI here

        }


推荐阅读