【问题标题】:Views in Fragment Return NullPointerException After Selecting Navigation Item选择导航项后,Fragment 中的视图返回 NullPointerException
【发布时间】:2017-12-27 13:20:29
【问题描述】:

我在一个活动中有一个导航抽屉,它将更新活动中的一个片段。一切正常,但是当我旋转设备并按下导航抽屉项目之一时,它会崩溃,因为片段中的视图为空。

在这里我实现了导航项选择。我将数据传递给片段实现的接口方法。

    @Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {

    // Call interface method that GalleriesFragment implements
    UpdateGalleries updateGalleries =  (UpdateGalleries) getSupportFragmentManager().getFragments().get(0);
    updateGalleries.fetchGalleriesOf(mSelectedCategory, categoryId);

    DrawerLayout drawer = findViewById(R.id.drawer_layout);
    drawer.closeDrawer(GravityCompat.START);

    return false;
}

这是我实现接口方法的片段部分:

    @Override
public void fetchGalleriesOf(String category, String categoryId) {

    mProgressBar.setVisibility(View.VISIBLE); // progressBar is null

    // Listen for firebase values
    listenToGalleries();

    // Attach listener to reference
    if(category.equals("Home")){
        category = "Recently added";
        References.galleriesRef.orderByChild(Constants.TIMESTAMP).addValueEventListener(mGalleriesListener);
    }else {
        References.galleriesRef.orderByChild(Constants.CATEGORY_ID).equalTo(categoryId)
                .addValueEventListener(mGalleriesListener);
    }

    mCategoryTV.setText(category);

}// End fetchGalleriesOf

这里是activity_main.xml中的片段:

<fragment 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"
android:name="com.thunderbolt.thebolt.ui.fragment.GalleriesFragment"
tools:context=".ui.activity.MainActivity"/>

fragment中的mProgressBar和mCategoryTV尽管在fragment的onCreateView中初始化,却返回空指针异常:

    @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    // Inflate the layout for this fragment
    View rootView = inflater.inflate(R.layout.fragment_gallery, container, false);

    // Reset list
    mGalleries = new ArrayList<>();
    mGalleriesAdapter = new GalleriesAdapter(mGalleries, this);

    mRecyclerView = rootView.findViewById(R.id.rv_galleries);
    mRecyclerView.setAdapter(mGalleriesAdapter);

    LinearLayoutManager layoutManager = new LinearLayoutManager(getContext());
    mRecyclerView.setLayoutManager(layoutManager);
    mRecyclerView.setHasFixedSize(true);

    mCategoryTV = rootView.findViewById(R.id.tv_category);
    mCategoryTV.setText(mCategory);

    mProgressBar = rootView.findViewById(R.id.progress_bar);
    mProgressBar.setVisibility(View.VISIBLE);
    mNoDataTV = rootView.findViewById(R.id.tv_no_data);

    return rootView;
}

编辑: 崩溃日志:

E/AndroidRuntime: 致命异常: main 进程:com.thunderbolt.thebolt,PID:31441 java.lang.NullPointerException:尝试在空对象引用上调用虚拟方法“void android.widget.ProgressBar.setVisibility(int)” 在 com.thunderbolt.thebolt.ui.fragment.GalleriesFragment.fetchGalleriesOf(GalleriesFragment.java:146) 在 com.thunderbolt.thebolt.ui.activity.MainActivity.onNavigationItemSelected(MainActivity.java:191) 在 android.support.design.widget.NavigationView$1.onMenuItemSelected(NavigationView.java:154) 在 android.support.v7.view.menu.MenuBuilder.dispatchMenuItemSelected(MenuBuilder.java:822) 在 android.support.v7.view.menu.SubMenuBuilder.dispatchMenuItemSelected(SubMenuBuilder.java:89) 在 android.support.v7.view.menu.MenuItemImpl.invoke(MenuItemImpl.java:171) 在 android.support.v7.view.menu.MenuBuilder.performItemAction(MenuBuilder.java:973) 在 android.support.design.internal.NavigationMenuPresenter$1.onClick(NavigationMenuPresenter.java:342) 在 android.view.View.performClick(View.java:5232) 在 android.view.View$PerformClick.run(View.java:21289) 在 android.os.Handler.handleCallback(Handler.java:739) 在 android.os.Handler.dispatchMessage(Handler.java:95) 在 android.os.Looper.loop(Looper.java:168) 在 android.app.ActivityThread.main(ActivityThread.java:5885) 在 java.lang.reflect.Method.invoke(本机方法) 在 com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:797) 在 com.android.internal.os.ZygoteInit.main(ZygoteInit.java:687)

【问题讨论】:

  • 添加崩溃日志。
  • 查看我添加 Logcat 的编辑
  • 你在哪里初始化 progressBar ?我在onCreateView() 中没有看到它。
  • 它在 onCreateView() 的底部
  • 不,不是。底部是mProgressBar 而不是progressBar

标签: android android-activity fragment navigation-drawer


【解决方案1】:

Fragment尝试添加这个来保存它的数据:

@Override
public void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);

    // Save the fragment's state
    setRetainInstance(true);
}

在您的 Activity 中,不要重新添加片段,否则它们会重叠。即来自this

// However, if we're being restored from a previous state,
// then we don't need to do anything and should return or else
// we could end up with overlapping fragments.
if (savedInstanceState != null) {
    return;
}

【讨论】:

  • 谢谢,这防止了崩溃,但它在导航抽屉项目单击时禁用了片段更新
  • 也许您没有在 Fragment 或 Activity 中使用Bundle savedInstanceState,并且您重置了一些数据。
  • 感谢您的帮助,我解决了这个问题。这是因为xml中的fragment在纵向中没有id属性,而在横向xml中却有。
  • 不客气,别忘了关闭问题:)
【解决方案2】:

Android 基本设备轮换流程

在正常情况下,当您旋转设备时,您的活动将被销毁并重新创建。

所以在获取片段之前先检查片段列表的大小。

if(getSupportFragmentManager().getFragments().size() > 0) {
    UpdateGalleries updateGalleries =  (UpdateGalleries) getSupportFragmentManager().getFragments().get(0);
    updateGalleries.fetchGalleriesOf(mSelectedCategory, categoryId);
}

【讨论】:

    【解决方案3】:

    问题是因为 xml 中的片段声明没有纵向模式的 id 属性,但有横向模式的 id。现在我为两者提供了一个 id:

    <fragment xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/fragment_galleries"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:name="com.thunderbolt.thebolt.ui.fragment.GalleriesFragment"
    tools:context=".ui.activity.MainActivity"/>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-09-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-11-18
      相关资源
      最近更新 更多