66

I sometimes get the following exception when working with Fragments:

FATAL EXCEPTION: main
java.lang.NullPointerException
    at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:591)
    at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1416)
    at android.support.v4.app.FragmentManagerImpl$1.run(FragmentManager.java:420)
    at android.os.Handler.handleCallback(Handler.java:615)
    at android.os.Handler.dispatchMessage(Handler.java:92)
    at android.os.Looper.loop(Looper.java:137)
    at android.app.ActivityThread.main(ActivityThread.java:4745)
    at java.lang.reflect.Method.invokeNative(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:511)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
    at dalvik.system.NativeStart.main(Native Method)

The exception occurs when run() of BackStackRecord is called through execPendingTransactions(), when it tries to remove a fragment from the manager.

case OP_REMOVE: {
  Fragment f = op.fragment;
  f.mNextAnim = op.exitAnim; <----
  mManager.removeFragment(f, mTransition, mTransitionStyle);
}
break;

I can't seem to figure out what exactly is causing this? I think it has to do with the backstack of fragments not being cleaned up right when removing fragments.

3 Answers 3

161

Answering my own question:

This exception is (eventually) thrown when you call FragmentTransaction.remove(null); and FragmentTransaction.commit();

EDIT: And also, like Twice Circled and shinyuX point out in the comment; when calling the show(null) or add(null), attach(null) and detach(null) methods, and probably also hide(null)

After calling commit(), the transaction will be queued in the FragmentManager. As a result, when the operation is being processed after you explicitly call FragmentManager.executePendingTransactions(), or when the FragmentManager queue thread calls it, it throws a NullPointerException.

In my case, I was maintaining fragment states in a global object. There I checked if the fragment was showing or not, and then removed visible fragments. But because I started a new FragmentActivity, these states were still set to true while they were not visible. So this is a design error.

Other than fixing the design error, the solution was simple: check whether FragmentManager.findFragmentByTag() returned null before removing the fragment.

7
  • 14
    Good answer - This helped me solve my own issue. One thing to note, you will get the same error when you call FragmentTransaction.show(null), .hide(null) etc. not just .remove(null). Hopefully this will help others track down their issue. Commented Feb 5, 2013 at 11:20
  • 1
    Helped me A LOT ! Note that it'll fail with any action sent with a null fragment (in my case attach detach
    – shinyuX
    Commented Mar 6, 2014 at 14:17
  • 1
    Thanks for this, definitely helped. In my case I was navigating back to a destroyed FragmentActivity where I kept references to fragments in fields. The solution was to use findFragmentByTag and re-assign these fields on the activity's onCreate method - if savedInstanceState != null (in which case the fragments wouldn't have been recreated - see pattern here).
    – kassim
    Commented Jun 16, 2014 at 15:13
  • 2
    this should totally crash on the actual hide,show... call, so that the stacktrace is actually usable ...
    – njzk2
    Commented Aug 20, 2014 at 19:57
  • Couldn't agree more @njzk2
    – NickL
    Commented Jan 6, 2015 at 12:26
0

The one reason why it happens it is invoking

getSupportFragmentManager().beginTransaction().remove(fragment)

while fragment is null

-2

I don't use tag to create the fragments (they works like TabBar containers).

So, it works when change Tab, but if I press back button I got the same error.

At onDestroyView method I found fragment instance with FragmentManager#findFragmentById, however FragmentManager#findFragmentByTag returns null, sure.

class MyFragment extends ListFragment {

@Override
public void onDestroyView() {
    super.onDestroyView();

    if (this.mapFragment != null
            && getFragmentManager().findFragmentById(
                    this.mapFragment.getId()) != null) {

        getFragmentManager().beginTransaction().remove(this.mapFragment)
                .commit();
        this.mapFragment = null;
    }

}
}
2
  • 2
    Why is it necessary to set mapFragment to null? Commented Oct 27, 2013 at 10:07
  • 1
    A question worth answering :- Why is it necessary to set mapFragment to null?
    – nmxprime
    Commented Dec 17, 2014 at 15:12

Not the answer you're looking for? Browse other questions tagged or ask your own question.