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.

Paul Lammertsma
  • 37,593
  • 16
  • 136
  • 187
NickL
  • 4,258
  • 2
  • 21
  • 38

3 Answers3

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.

NickL
  • 4,258
  • 2
  • 21
  • 38
  • 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. – Twice Circled Feb 05 '13 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 Mar 06 '14 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](http://developer.android.com/training/basics/fragments/fragment-ui.html)). – kassim Jun 16 '14 at 15:13
  • 2
    this should totally crash on the actual `hide`,`show`... call, so that the stacktrace is actually usable ... – njzk2 Aug 20 '14 at 19:57
  • Couldn't agree more @njzk2 – NickL Jan 06 '15 at 12:26
  • I call "replace" and the parameter isn't null. How come I still get this issue? – android developer Feb 17 '15 at 14:15
  • .hide(null) in my case – Tushar Pandey Mar 03 '15 at 11:34
0

The one reason why it happens it is invoking

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

while fragment is null

Pavlo Zoria
  • 666
  • 7
  • 7
-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;
    }

}
}
seufagner
  • 1,290
  • 2
  • 18
  • 25