java - studio - Android FragmentManager BackStackRecord.run lanzando NullPointerException
how to implement fragments in android studio (2)
A veces obtengo la siguiente excepción cuando trabajo con 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)
La excepción se produce cuando se llama a run()
de BackStackRecord
través de execPendingTransactions()
, cuando intenta eliminar un fragmento del administrador.
case OP_REMOVE: {
Fragment f = op.fragment;
f.mNextAnim = op.exitAnim; <----
mManager.removeFragment(f, mTransition, mTransitionStyle);
}
break;
Parece que no puedo averiguar qué está causando esto exactamente. Creo que tiene que ver con el backstack de fragmentos que no se limpian correctamente al eliminar fragmentos.
No uso etiquetas para crear los fragmentos (funcionan como contenedores TabBar).
Entonces, funciona cuando cambio la pestaña, pero si presiono el botón Atrás, recibí el mismo error.
En el método onDestroyView encontré la instancia de fragmento con FragmentManager # findFragmentById, sin embargo FragmentManager # findFragmentByTag devuelve null, claro.
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;
}
}
}
Respondiendo mi propia pregunta:
Esta excepción se lanza (eventualmente) cuando llamas a FragmentTransaction.remove(null);
y FragmentTransaction.commit();
EDITAR: Y también, como Twice Circled y shinyuX señalan en el comentario; al llamar a los métodos show(null)
o add(null)
, attach(null)
y detach(null)
, y probablemente también hide(null)
Después de llamar a commit()
, la transacción se pondrá en cola en FragmentManager. Como resultado, cuando la operación se está procesando después de llamar explícitamente a FragmentManager.executePendingTransactions()
, o cuando el hilo de cola de FragmentManager lo llama, arroja una NullPointerException
.
En mi caso, mantuve estados de fragmentos en un objeto global. Allí revisé si el fragmento se mostraba o no, y luego eliminé los fragmentos visibles. Pero debido a que comencé una nueva FragmentActivity, estos estados todavía se configuraron como verdaderos mientras no eran visibles. Entonces este es un error de diseño.
Aparte de corregir el error de diseño, la solución era simple: verificar si FragmentManager.findFragmentByTag()
devolvía el null
antes de eliminar el fragmento.