1

I have problem with fragment's backStack. Firstly, my structure is: I have activity with fragmentManager, new fragments added with method add() and with adding to back stack. So, when I have at list 2 fragments in backstack and when I have orientation changing, activity is recreated, and fragment restored, but when I call onBackPressed() and call popBackStackImmediate() I get an exception: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.support.v4.app.Fragment.setNextAnim(int)' on a null object reference.

It seem's, that we have null fragment in back stack, but I've checked it, this fragments weren't null. So, can you help solve this problem?

I add fragments like this:

FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();

fragmentTransaction
    .setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);

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

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

In onBackPressed() I have same behaivor:

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

Full stackTrace is:

 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)

line 164 is:

super.onBackPressed()

Full code of base activity with adding logic:

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 Answers1

0

The condition of popping the fragment itself is written logically in reverse. super.onBackPressed() will pop the fragment if it is present in the backstack.So if the getBackStackEntryCount() is greater than zero you need to call the super method or else finish the activity when there is no fragments in backstack.

if (fragmentManager.getBackStackEntryCount() >=0) {
    getSupportFragmentManager().popBackStackImmediate()
} else {
    super.onBackPressed();
}
Sharath kumar
  • 4,064
  • 1
  • 14
  • 20