Android FragmentManager BackStackRecord.run lance 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 cela? Je pense que cela a à voir avec le backstack de fragments qui ne sont pas nettoyés lors de la suppression de fragments.

Répondre à ma propre question:

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

EDIT: Et aussi, comme Twice Circled et shinyuX le soulignent dans le commentaire; lors de l’appel de la méthode show(null) ou add(null) , attach(null) et detach(null) method, et probablement aussi hide(null)

Après avoir appelé commit() , la transaction sera mise en queue dans FragmentManager. Par conséquent, lorsque l’opération est en cours de traitement après l’appel explicite de FragmentManager.executePendingTransactions() ou lorsque le thread de queue FragmentManager l’appelle, une NullPointerException .

Dans mon cas, je maintenais des états de fragment dans un object global. Là, j’ai vérifié si le fragment montrait ou non, puis enlevé les fragments visibles. Mais parce que j’ai lancé un nouveau 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() renvoyé la valeur null avant de supprimer le fragment.

La seule raison pour laquelle il se produit, c’est l’invocation

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

alors que fragment est nul

Je n’utilise pas tag pour créer les fragments (ils fonctionnent comme des conteneurs TabBar).

Donc, ça marche quand on change Tab, mais si j’appuie sur le bouton retour j’ai la même erreur.

A la méthode onDestroyView, j’ai trouvé une instance de fragment avec FragmentManager # findFragmentById, mais FragmentManager # findFragmentByTag renvoie 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; } } }