popBackStackImmediate()时出现NullPointerException

时间:2017-12-08 11:55:03

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

我有片段的backStack问题。首先,我的结构是:我有使用fragmentManager的活动,使用方法add()添加的新片段以及添加到后台堆栈。所以,当我在backstack中列出2个片段时,当我更改方向时,重新创建活动,并恢复片段,但是当我调用 onBackPressed()并调用 popBackStackImmediate()我得到一个异常: java.lang.NullPointerException:尝试调用虚方法' void android.support.v4.app.Fragment.setNextAnim(int)'在空对象引用上。

似乎我们在后台堆栈中有空片段,但是我已经检查过了,这些片段并不是空的。那么,你能帮忙解决这个问题吗?

我添加这样的片段:

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();
 }

完整的stackTrace是:

 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();
}
}

1 个答案:

答案 0 :(得分:0)

弹出片段本身的条件是逻辑反过来写的。如果片段存在于backstack中,super.onBackPressed()将弹出片段。如果getBackStackEntryCount()大于零,则需要调用super方法,否则当{{1}中没有片段时完成活动}}

backstack