【问题标题】:NullPointerException when popBackStackImmediate()popBackStackImmediate() 时出现 NullPointerException
【发布时间】:2018-05-22 16:09:14
【问题描述】:

我对 Fragment 的 backStack 有疑问。首先,我的结构是:我使用 fragmentManager 进行活动,使用 add() 方法添加新片段并添加到后台堆栈。因此,当我在 backstack 中有列表 2 片段并且当我改变方向时,重新创建活动并恢复片段,但是当我调用 onBackPressed() 并调用 popBackStackImmediate() 我得到一个异常:java.lang.NullPointerException: Attempt to invoke virtual method 'void android.support.v4.app.Fragment.setNextAnim(int)' on an null object reference。

看起来,我们在后栈中有空片段,但我已经检查过了,这个片段不是空的。那么,您能帮忙解决这个问题吗?

我添加这样的片段:

FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();

fragmentTransaction
    .setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);

if (previousFragment != null) {
   fragmentTransaction.hide(previousFragment);
}

fragmentTransaction.add(containerViewId, fragment, fragmentTag)
            .addToBackStack(fragmentTag)
            .commit();

在 onBackPressed() 我有同样的行为:

 if (fragmentManager.getBackStackEntryCount() == 1) {
    finish();
 } else {
   super.onBackPressed();
 }

完整的堆栈跟踪是:

 java.lang.NullPointerException: Attempt to invoke virtual method 'void android.support.v4.app.Fragment.setNextAnim(int)' on a null object reference
                                                                             at android.support.v4.app.BackStackRecord.executePopOps(BackStackRecord.java:826)
                                                                             at android.support.v4.app.FragmentManagerImpl.executeOps(FragmentManager.java:2587)
                                                                             at android.support.v4.app.FragmentManagerImpl.executeOpsTogether(FragmentManager.java:2377)
                                                                             at android.support.v4.app.FragmentManagerImpl.removeRedundantOperationsAndExecute(FragmentManager.java:2332)
                                                                             at android.support.v4.app.FragmentManagerImpl.popBackStackImmediate(FragmentManager.java:851)
                                                                             at android.support.v4.app.FragmentManagerImpl.popBackStackImmediate(FragmentManager.java:794)
                                                                             at net.lampa.tablet.nightexpress.view.activities.OrderFinalActivity.onBackPressed(OrderFinalActivity.java:147)
                                                                             at net.lampa.tablet.nightexpress.view.activities.OrderFinalActivity.onOptionsItemSelected(OrderFinalActivity.java:183)
                                                                             at android.app.Activity.onMenuItemSelected(Activity.java:2914)
                                                                             at android.support.v4.app.FragmentActivity.onMenuItemSelected(FragmentActivity.java:380)
                                                                             at android.support.v7.app.AppCompatActivity.onMenuItemSelected(AppCompatActivity.java:195)
                                                                             at android.support.v7.view.WindowCallbackWrapper.onMenuItemSelected(WindowCallbackWrapper.java:108)
                                                                             at android.support.v7.view.WindowCallbackWrapper.onMenuItemSelected(WindowCallbackWrapper.java:108)
                                                                             at android.support.v7.widget.ToolbarWidgetWrapper$1.onClick(ToolbarWidgetWrapper.java:187)
                                                                             at android.view.View.performClick(View.java:5204)
                                                                             at android.view.View$PerformClick.run(View.java:21153)
                                                                             at android.os.Handler.handleCallback(Handler.java:739)
                                                                             at android.os.Handler.dispatchMessage(Handler.java:95)
                                                                             at android.os.Looper.loop(Looper.java:148)
                                                                             at android.app.ActivityThread.main(ActivityThread.java:5417)
                                                                             at java.lang.reflect.Method.invoke(Native Method)
                                                                             at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
                                                                             at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)

第 164 行是:

super.onBackPressed()

带有添加逻辑的基本活动的完整代码:

public abstract class BaseActivity extends AppCompatActivity {

private Unbinder uninder;

protected BaseFragment currentFragment;
protected BaseFragment previousFragment;
protected FragmentManager fragmentManager;

private Map<Integer, ArrayList<String>> filterTagsMap = new TreeMap<>();

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    Class cls = getClass();
    if (!cls.isAnnotationPresent(Layout.class)) {
        return; // Layout annotation is required
    }
    Annotation annotation = cls.getAnnotation(Layout.class);
    setContentView(((Layout) annotation).id());
    uninder = ButterKnife.bind(this);

    if(fragmentManager == null) {
        fragmentManager = getSupportFragmentManager();
    }

    currentFragment = getDefaultFragment();

    inject();  // inject dependencies
    setupDefaultValues();
}

public ApplicationComponent getApplicationComponent() {
    return ((NEApplication) getApplication()).getApplicationComponent();
}

public abstract void setupDefaultValues();

public void closeCurrentFragmentInBackStack() {
    fragmentManager.popBackStackImmediate();
}

public void showFragment(int containerViewId, BaseFragment fragment, boolean needToRefreshBackStack) {

    if (needToRefreshBackStack && fragmentManager.getBackStackEntryCount() > 0) {
        int indexToDelete = (fragment.getClass().getSimpleName()
                .equals(fragmentManager.getBackStackEntryAt(0).getName())) ? 0 : 1;
        int backStackFragmentsCount = fragmentManager.getBackStackEntryCount();
        for (int i = backStackFragmentsCount - 1; i >= indexToDelete; i--) {
            int backStackId = fragmentManager.getBackStackEntryAt(i).getId();
            fragmentManager.popBackStack(backStackId, FragmentManager.POP_BACK_STACK_INCLUSIVE);
        }
    }

    previousFragment = currentFragment;
    currentFragment = fragment;

    String fragmentTag = fragment.getClass().getSimpleName();
    FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();

    fragmentTransaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);

    if (previousFragment != null) {
        fragmentTransaction.hide(previousFragment);
    }
    fragmentTransaction.add(containerViewId, fragment, fragmentTag)
            .addToBackStack(fragmentTag)
            .commit();

}

protected abstract BaseFragment getDefaultFragment();

@Override
protected void onDestroy() {
    uninder.unbind();
    uninder = null;
    super.onDestroy();
}
}

【问题讨论】:

  • 不要发布屏幕截图,而是复制粘贴错误日志本身。谢谢。
  • 你可能没有添加 addtobackstack()
  • 我需要将它添加到后台
  • 你使用的是activity还是app compat activity?
  • 发布这个方法 setNextAnim(int)

标签: android nullpointerexception fragment orientation-changes fragment-backstack


【解决方案1】:

弹出片段本身的条件在逻辑上是相反的。 super.onBackPressed() 将在 backstack 中存在 Fragment 时将其弹出。因此,如果 getBackStackEntryCount() 大于零,则需要调用 super 方法,否则在 backstack 中没有 Fragment 时完成活动。

if (fragmentManager.getBackStackEntryCount() >=0) {
    getSupportFragmentManager().popBackStackImmediate()
} else {
    super.onBackPressed();
}

【讨论】:

  • 有什么区别?我告诉过当调用 popBackStackImmediate() 时它会崩溃
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-12-29
  • 2013-12-29
  • 2013-12-19
  • 2017-09-01
  • 2022-01-19
  • 2021-04-11
相关资源
最近更新 更多