wake-up-neo.com

Android FragmentManager BackStackRecord.run löst NullPointerException aus

Bei der Arbeit mit Fragmenten erhalte ich manchmal die folgende Ausnahme:

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)

Die Ausnahme tritt auf, wenn run() von BackStackRecord durch execPendingTransactions() aufgerufen wird, wenn versucht wird, ein Fragment aus dem Manager zu entfernen.

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

Ich kann nicht herausfinden, was genau das verursacht? Ich denke, es hat damit zu tun, dass der Backstack von Fragmenten beim Entfernen von Fragmenten nicht richtig aufgeräumt wird.

65
NickL

Beantwortung meiner eigenen Frage:

Diese Ausnahme wird (eventuell) ausgelöst, wenn Sie FragmentTransaction.remove(null); und FragmentTransaction.commit(); aufrufen.

EDIT: Und auch, wie Twice Circled und ShinyuX im Kommentar hervorheben; beim Aufruf der Methoden show(null) oder add(null), attach(null) und detach(null) und wahrscheinlich auch hide(null)

Nach dem Aufruf von commit() wird die Transaktion im FragmentManager in die Warteschlange gestellt. Wenn der Vorgang verarbeitet wird, nachdem Sie explizit FragmentManager.executePendingTransactions() aufgerufen haben, oder wenn der FragmentManager-Warteschlangenthread ihn aufruft, wird eine NullPointerException ausgegeben.

In meinem Fall habe ich Fragmentzustände in einem globalen Objekt beibehalten. Dort überprüfte ich, ob das Fragment angezeigt wurde oder nicht, und entfernte dann sichtbare Fragmente. Da ich jedoch eine neue FragmentActivity gestartet habe, wurden diese Zustände immer auf wahr gesetzt, solange sie nicht sichtbar waren. Das ist also ein Designfehler.

Abgesehen von der Behebung des Designfehlers war die Lösung einfach: Prüfen Sie, ob FragmentManager.findFragmentByTag()null zurückgegeben hat, bevor Sie das Fragment entfernen.

159
NickL

Der einzige Grund, warum es passiert, ist der Aufruf 

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

während fragment null ist

0
Pavlo Zorya