web-dev-qa-db-fra.com

Android FragmentManager BackStackRecord.run levant une exception NullPointerException

J'obtiens parfois l'exception suivante lorsque je travaille avec 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)

L'exception se produit lorsque run() de BackStackRecord est appelé via execPendingTransactions(), lorsqu'il tente de supprimer un fragment du gestionnaire.

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

Je n'arrive pas à comprendre ce qui cause exactement ça? Je pense que cela a à voir avec le tas de fragments ne sont pas nettoyés correctement lors de la suppression des fragments.

65
NickL

Répondre à ma propre question:

Cette exception est (éventuellement) levée lorsque vous appelez FragmentTransaction.remove(null); et FragmentTransaction.commit();

EDIT: Et aussi, comme deux fois cerclé et shinyuX soulignent dans le commentaire; en appelant les méthodes show(null) ou add(null), attach(null) et detach(null), et probablement aussi hide(null)

Après avoir appelé commit(), la transaction sera mise en file d'attente dans FragmentManager. Par conséquent, lorsque l'opération est en cours de traitement après l'appel explicitement de FragmentManager.executePendingTransactions() ou lorsque le thread de la file d'attente de FragmentManager l'appelle, elle renvoie une NullPointerException.

Dans mon cas, je maintenais des états de fragment dans un objet global. Là, j'ai vérifié si le fragment était visible ou non, puis j'ai retiré les fragments visibles. Mais comme j'ai commencé une nouvelle FragmentActivity, ces états étaient toujours définis sur true alors qu'ils n'étaient pas visibles. C'est donc une erreur de conception.

Outre la correction de l'erreur de conception, la solution était simple: vérifiez si FragmentManager.findFragmentByTag() a retourné null avant de supprimer le fragment.

159
NickL

La seule raison pour laquelle il arrive, c'est l'invocation 

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

alors que fragment est null

0
Pavlo Zorya