Android FragmentManager BackStackRecord.run throwing NullPointerException
Asked Answered
H

3

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.

Headland answered 15/11, 2012 at 8:18 Comment(0)
H
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.

Headland answered 15/11, 2012 at 10:3 Comment(7)
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.Dunstable
Helped me A LOT ! Note that it'll fail with any action sent with a null fragment (in my case attach detachPlumlee
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).Staffordshire
this should totally crash on the actual hide,show... call, so that the stacktrace is actually usable ...Caryophyllaceous
Couldn't agree more @CaryophyllaceousHeadland
I call "replace" and the parameter isn't null. How come I still get this issue?Trangtranquada
.hide(null) in my caseJacobin
C
0

The one reason why it happens it is invoking

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

while fragment is null

Corotto answered 20/8, 2018 at 8:51 Comment(0)
G
-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;
    }

}
}
Granvillegranvillebarker answered 12/3, 2013 at 18:25 Comment(2)
Why is it necessary to set mapFragment to null?Gratiana
A question worth answering :- Why is it necessary to set mapFragment to null?Mt

© 2022 - 2024 — McMap. All rights reserved.