带导航抽屉的 PreferenceActivity 抛出空指针异常

PreferenceActivity with Navigation Drawer Throws Null Pointer Exception

我有一个运行良好的 PreferenceActivity。然后,我决定给它添加一个导航抽屉,并根据我的其他 activity 布局编辑布局,这些布局也有可用的导航抽屉。但是,这样做之后,我的 PreferenceActivity 停止打开并开始在开始时抛出 NPE。我什至无法再打开 activity。显然,问题出在 onCreate 中,也出在 logcat 中所述的 onClick 方法中。然而,在这个 onCreate 活动中有两个 onClick,我没有看到它们如何导致 NPE,因为它们在我的其他工作活动中完全相同。根据默认的 DrawerLayout 实现,我的布局 xml 被分成 3 个 xml。事不宜迟,这里是代码和 xml:

偏好活动:

public class FirstYearCoursesActivity extends PreferenceActivity
    implements NavigationView.OnNavigationItemSelectedListener {

private AppCompatDelegate mDelegate;
Toolbar toolbar;

@Override
protected void onCreate(Bundle savedInstanceState) {
    getDelegate().installViewFactory();
    getDelegate().onCreate(savedInstanceState);
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_first_year_courses);
    toolbar = (Toolbar) findViewById(R.id.toolbar);
    setSupportActionBar((toolbar));
    Window window = this.getWindow();
    window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
    window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
    window.setStatusBarColor(this.getResources().getColor(R.color.colorPrimaryDark));
    addPreferencesFromResource(R.xml.prefs);
    DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
    ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
            this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
    drawer.setDrawerListener(toggle);
    toggle.syncState();

    NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view2);
    navigationView.setNavigationItemSelectedListener(this);
    View headerView = navigationView.getHeaderView(0);
    ImageButton logoutButton = (ImageButton) headerView.findViewById(R.id.logoutButton);
    logoutButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Intent intent = new Intent(FirstYearCoursesActivity.this, LoginActivity.class);
            startActivity(intent);
        }
    });
}

@Override
public void onBackPressed() {
    DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
    if (drawer.isDrawerOpen(GravityCompat.START)) {
        drawer.closeDrawer(GravityCompat.START);
    } else {
        super.onBackPressed();
    }
}

@Override
protected void onPause() {
    final DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
    final Handler handler = new Handler();
    if (drawer.isDrawerOpen(GravityCompat.START)) {
        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                drawer.closeDrawer(GravityCompat.START);
            }
        }, 200);
        super.onPause();
    } else {
        super.onPause();
    }
}
private void setSupportActionBar(@Nullable Toolbar toolbar) {
    getDelegate().setSupportActionBar(toolbar);
}

private AppCompatDelegate getDelegate() {
    if (mDelegate == null) {
        mDelegate = AppCompatDelegate.create(this, null);
    }
    return mDelegate;
}

@Override
public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) {

    String key = preference.getKey();
        switch (key) {
            case "math119":
                Intent intent = new Intent(FirstYearCoursesActivity.this, Math119Activity.class);
                startActivity(intent);
                break;
            default:
                Toast.makeText(this, "Other Click", Toast.LENGTH_SHORT).show();
                break;
        }

    return super.onPreferenceTreeClick(preferenceScreen, preference);
}

@SuppressWarnings("StatementWithEmptyBody")
@Override
public boolean onNavigationItemSelected(MenuItem item) {
   // to be filled
    int id = item.getItemId();

    if (id == R.id.nav_camera) {

    } else if (id == R.id.nav_gallery) {

    } else if (id == R.id.nav_slideshow) {

    } else if (id == R.id.nav_manage) {

    } else if (id == R.id.nav_share) {

    } else if (id == R.id.nav_send) {

    }
    return true;
}
}

activity.xml:

<android.support.v4.widget.DrawerLayout
android:id="@+id/drawer_layout"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">

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

<android.support.design.widget.NavigationView
    android:id="@+id/nav_view2"
    android:layout_width="250dp"
    android:layout_height="match_parent"
    android:layout_gravity="start"
    android:fitsSystemWindows="true"
    app:headerLayout="@layout/nav_header_main"
    app:menu="@menu/activity_main_drawer"
    android:background="#ffffffff"
    app:itemTextColor="#000000"
    app:itemTextAppearance="@style/TextAppearance.AppCompat.Body1"/>
</android.support.v4.widget.DrawerLayout>

app_bar.xml:

<android.support.design.widget.CoordinatorLayout
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"
android:fitsSystemWindows="true"
tools:context=".activities.FirstYearCoursesActivity">

<android.support.design.widget.AppBarLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:theme="@style/AppTheme.AppBarOverlay">

    <android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:background="?attr/colorPrimary"
        app:popupTheme="@style/AppTheme.PopupOverlay"/>

</android.support.design.widget.AppBarLayout>

<include layout="@layout/content_first_year_courses"/>

</android.support.design.widget.CoordinatorLayout>

content.xml:

<LinearLayout
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"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
tools:context=".activities.FirstYearCoursesActivity"
tools:showIn="@layout/app_bar_first_year_courses"
android:orientation="vertical">

</LinearLayout>

nav_header.xml:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
          android:layout_width="match_parent"
          android:layout_height="140dp"
          android:background="@drawable/profilebanner"
          android:gravity="bottom"
          android:orientation="vertical"
          android:theme="@style/ThemeOverlay.AppCompat.Dark"
          android:id="@+id/header">

<ImageButton
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/logoutButton"
    android:src="@drawable/ic_power_settings_new_white_18dp"
    android:background="#00ffffff"
    android:layout_alignParentTop="true"
    android:layout_alignParentEnd="true"
    android:layout_marginTop="30dp"
    android:layout_marginRight="10dp"/>

<RelativeLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/headerClick"
    android:layout_alignParentBottom="true"
    android:layout_alignParentStart="true"
    android:paddingLeft="10dp"
    android:paddingRight="10dp"
    android:paddingBottom="10dp"
    android:paddingTop="20dp">

    <ImageView
        android:layout_width="65dp"
        android:layout_height="65dp"
        android:id="@+id/imageView"
        android:background="@drawable/onur"
        android:layout_centerVertical="true"
        android:layout_alignParentStart="false"
        android:layout_alignBottom="@+id/textView3"
        android:layout_marginBottom="-20dp"/>

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Onur Çevik"
        android:textAppearance="@style/TextAppearance.AppCompat.Body1"
        android:id="@+id/textView2"
        android:textSize="13sp"
        android:layout_toRightOf="@+id/imageView"
        android:layout_marginLeft="25dp"
        android:layout_marginTop="45dp"/>

    <TextView
        android:id="@+id/textView3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Environmental Engineering"
        android:textSize="11sp"
        android:layout_toRightOf="@+id/imageView"
        android:layout_marginLeft="25dp"
        android:layout_below="@+id/textView2"
        android:layout_alignParentStart="false"/>

</RelativeLayout>

</RelativeLayout>

prefs.xml:

<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
android:key="firstyearprefs">
<Preference
    android:title="Math-119"
    android:key="math119"/>
<Preference
    android:title="Math-120"
    android:key="math120"/>
<Preference
    android:title="Phys-105"
    android:key="phys105"/>
<Preference
    android:title="Phys-106"
    android:key="phys106"/>
<Preference
    android:title="Chem-107"
    android:key="chem107"/>
<Preference
    android:title="Eng-101"
    android:key="eng101"/>
<Preference
    android:title="Eng-102"
    android:key="eng102"/>
<Preference
    android:title="Ce-101"
    android:key="ce101"/>

</PreferenceScreen>

logcat:

02-08 02:10:35.415 30815-30815/com.theoc.proto E/AndroidRuntime: FATAL EXCEPTION: main
                                                             Process: com.theoc.proto, PID: 30815
                                                             java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.ListView.setOnItemClickListener(android.widget.AdapterView$OnItemClickListener)' on a null object reference
                                                                 at android.preference.PreferenceScreen.bind(PreferenceScreen.java:143)
                                                                 at android.preference.PreferenceActivity.bindPreferences(PreferenceActivity.java:1419)
                                                                 at android.preference.PreferenceActivity.access[=16=]0(PreferenceActivity.java:123)
                                                                 at android.preference.PreferenceActivity.handleMessage(PreferenceActivity.java:230)
                                                                 at android.os.Handler.dispatchMessage(Handler.java:102)
                                                                 at android.os.Looper.loop(Looper.java:135)
                                                                 at android.app.ActivityThread.main(ActivityThread.java:5272)
                                                                 at java.lang.reflect.Method.invoke(Native Method)
                                                                 at java.lang.reflect.Method.invoke(Method.java:372)
                                                                 at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:909)
                                                                 at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:704)

编辑:

值得一提的是,我对 activity 进行了三次检查,它是在列表项单击时导致此 PreferenceActivity 的适配器。我反转了我所有的抽屉布局实现,并且我能够通过父 activity 打开此 PreferenceActivity。 Navigation Drawer 代码或布局是搞乱它的代码。我得到了 listview.onclick(adapter) NPE,因为我的列表项点击父级 activity 进入了一个空引用,在本例中它是 PreferenceActivity 本身。此外,调试在 PreferenceActivity 的 onCreate 中没有显示任何 null,除了 savedInstanceState。

我能够使用您的代码重现相同的 NPE 并通过使用片段代替 addPreferencesFromResource 调用(注意它已被弃用)来修复它,如这些线程中所述:

Android: Preference Fragment with a Navigation Drawer's Fragment

What to use instead of "addPreferencesFromResource" in a PreferenceActivity?

虽然在我的版本中,首选项视图与工具栏重叠,但我不确定 activity 布局应该如何解决这个问题,也许在你的版本中就可以了。