65 votes

Android FragmentManager BackStackRecord.run levant une exception NullPointerException

EDIT2: Répondu à ma propre question ci-dessous

J'ai parfois l'exception suivante lorsque vous travaillez avec des Fragments:

11-15 09:04:21.023: E/AndroidRuntime(4057): FATAL EXCEPTION: main
11-15 09:04:21.023: E/AndroidRuntime(4057): java.lang.NullPointerException
11-15 09:04:21.023: E/AndroidRuntime(4057):     at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:591)
11-15 09:04:21.023: E/AndroidRuntime(4057):     at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1416)
11-15 09:04:21.023: E/AndroidRuntime(4057):     at android.support.v4.app.FragmentManagerImpl$1.run(FragmentManager.java:420)
11-15 09:04:21.023: E/AndroidRuntime(4057):     at android.os.Handler.handleCallback(Handler.java:615)
11-15 09:04:21.023: E/AndroidRuntime(4057):     at android.os.Handler.dispatchMessage(Handler.java:92)
11-15 09:04:21.023: E/AndroidRuntime(4057):     at android.os.Looper.loop(Looper.java:137)
11-15 09:04:21.023: E/AndroidRuntime(4057):     at android.app.ActivityThread.main(ActivityThread.java:4745)
11-15 09:04:21.023: E/AndroidRuntime(4057):     at java.lang.reflect.Method.invokeNative(Native Method)
11-15 09:04:21.023: E/AndroidRuntime(4057):     at java.lang.reflect.Method.invoke(Method.java:511)
11-15 09:04:21.023: E/AndroidRuntime(4057):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
11-15 09:04:21.023: E/AndroidRuntime(4057):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
11-15 09:04:21.023: E/AndroidRuntime(4057):     at dalvik.system.NativeStart.main(Native Method)

Je n'arrive pas à déterminer exactement quel en est la cause? Je pense que cela a à voir avec la backstack de fragments de ne pas être nettoyé à droite lors de la suppression de fragments.

EDIT1: L'exception se produit lors de l' run() de BackStackRecord est appelé thru execPendingTransactions(). Lorsqu'il tente de retirer un fragment de la part du gestionnaire.

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

160voto

NickL Points 2284

Pour répondre à ma propre question:

Cette exception est (enfin) lancée lorsque vous appelez FragmentTransaction.supprimer(null); et FragmentTransaction.commit();

EDIT: Et aussi, comme deux fois Encerclé et shinyuX point dans le commentaire; lors de l'appel de l' .show(null) ou .ajouter(null), joindre(null) et .détacher(null) des méthodes, et probablement aussi .masquer(null)

Après l'appel de commit(), la transaction sera mis en file d'attente dans le FragmentManager. En conséquence, lorsque l'opération est en cours de traitement après vous appeler explicitement FragmentManager.executePendingTransactions(), ou lorsque le FragmentManager file d'attente d'appels de fil, il jette un NullPointerException.

Dans mon cas, j'ai été le maintien de fragment unis dans un objet global. Là, j'ai vérifié si le fragment a été de montrer ou pas, et ensuite retiré visible fragments. Mais parce que j'ai commencé un nouveau FragmentActivity, ces états étaient encore défini à true, alors qu'ils n'étaient pas visibles. C'est donc une erreur de conception.

D'autres réparer l'erreur de conception, la solution est simple: vérifier si FragmentManager.findFragmentByTag() a retourné null avant de retirer le fragment.

-2voto

seufagner Points 458

Je n'utilise pas de balise pour créer les fragments (ils fonctionnent comme des conteneurs TabBar).

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

À la méthode onDestroyView, j'ai trouvé une instance de fragment avec FragmentManager # findFragmentById, cependant FragmentManager # findFragmentByTag renvoie null, bien sûr.

 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;
    }

}
}
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X