Cómo retener correctamente un DialogFragment a través de la rotación?
Tengo un FragmentActivity que recibe un DialogFragment.
El DialogFragment realizar las solicitudes de red y gestiona la autenticación de Facebook, así que necesito retenerlo durante la rotación.
- Seleccione la imagen de la galería en Android Fragment
- NotifyDataSetChanged () en Fragmento no está actualizando listview
- Cuándo usar FragmentManager :: putFragment y getFragment
- No puedo envolver mi cabeza alrededor de Android Fragments
- Cambiar programaticamente el color de la forma en la lista de capas
He leído todas las otras preguntas relacionadas con este tema, pero ninguna de ellas ha resuelto el problema.
Estoy utilizando putFragment y getFragment para guardar la instancia Fragment y volver a obtenerla durante la recreación de la actividad.
Sin embargo, siempre obtengo una excepción de puntero nulo en la llamada a getFragment en onRestoreInstanceState. También me gustaría mantener el diálogo de ser despedido durante la rotación, pero hasta ahora no puedo ni siquiera conservar la instancia de la misma.
Cualquier idea de lo que va mal?
Esto es lo que mi código parece actualmente:
public class OKLoginActivity extends FragmentActivity implements OKLoginDialogListener { private OKLoginFragment loginDialog; private static final String TAG_LOGINFRAGMENT = "OKLoginFragment"; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); FragmentManager fm = getSupportFragmentManager(); if(savedInstanceState == null) { loginDialog = new OKLoginFragment(); loginDialog.show(fm, TAG_LOGINFRAGMENT); } } @Override public void onSaveInstanceState(Bundle outState) { getSupportFragmentManager().putFragment(outState,TAG_LOGINFRAGMENT, loginDialog); } @Override public void onRestoreInstanceState(Bundle inState) { FragmentManager fm = getSupportFragmentManager(); loginDialog = (OKLoginFragment) fm.getFragment(inState, TAG_LOGINFRAGMENT); } }
Este es el rastreo de la pila de excepciones:
02-01 16:31:13.684: E/AndroidRuntime(9739): FATAL EXCEPTION: main 02-01 16:31:13.684: E/AndroidRuntime(9739): java.lang.RuntimeException: Unable to start activity ComponentInfo{io.openkit.example.sampleokapp/io.openkit.OKLoginActivity}: java.lang.NullPointerException 02-01 16:31:13.684: E/AndroidRuntime(9739): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2180) 02-01 16:31:13.684: E/AndroidRuntime(9739): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2230) 02-01 16:31:13.684: E/AndroidRuntime(9739): at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:3692) 02-01 16:31:13.684: E/AndroidRuntime(9739): at android.app.ActivityThread.access$700(ActivityThread.java:141) 02-01 16:31:13.684: E/AndroidRuntime(9739): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1240) 02-01 16:31:13.684: E/AndroidRuntime(9739): at android.os.Handler.dispatchMessage(Handler.java:99) 02-01 16:31:13.684: E/AndroidRuntime(9739): at android.os.Looper.loop(Looper.java:137) 02-01 16:31:13.684: E/AndroidRuntime(9739): at android.app.ActivityThread.main(ActivityThread.java:5039) 02-01 16:31:13.684: E/AndroidRuntime(9739): at java.lang.reflect.Method.invokeNative(Native Method) 02-01 16:31:13.684: E/AndroidRuntime(9739): at java.lang.reflect.Method.invoke(Method.java:511) 02-01 16:31:13.684: E/AndroidRuntime(9739): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793) 02-01 16:31:13.684: E/AndroidRuntime(9739): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560) 02-01 16:31:13.684: E/AndroidRuntime(9739): at dalvik.system.NativeStart.main(Native Method) 02-01 16:31:13.684: E/AndroidRuntime(9739): Caused by: java.lang.NullPointerException 02-01 16:31:13.684: E/AndroidRuntime(9739): at android.support.v4.app.FragmentManagerImpl.getFragment(FragmentManager.java:528) 02-01 16:31:13.684: E/AndroidRuntime(9739): at io.openkit.OKLoginActivity.onRestoreInstanceState(OKLoginActivity.java:62) 02-01 16:31:13.684: E/AndroidRuntime(9739): at android.app.Activity.performRestoreInstanceState(Activity.java:910) 02-01 16:31:13.684: E/AndroidRuntime(9739): at android.app.Instrumentation.callActivityOnRestoreInstanceState(Instrumentation.java:1131) 02-01 16:31:13.684: E/AndroidRuntime(9739): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2158)
- Duplicar ID con Fragmento en la página PagerAdapter
- OnCreateOptionsMenu dentro de Fragmentos
- Fragmentos dentro de un fragmento de la aplicación Android
- DialogFragment con espacio adicional debajo de ListView
- Transmisión de datos entre un fragmento y su actividad de contenedor
- Fragmento se bloquea con el paquete: no se puede marshal error de valor cuando onPause método se llama
- Cómo actualizar fragmento anterior después de cerrar una actividad que se inició dentro de un adaptador?
- Android: Cambiar el color del texto de Tab en FragmentActivity
Dentro de su DialogFragment, llama Fragment.setRetainInstance (boolean) con el valor true. No es necesario guardar el fragmento manualmente, el marco ya se encarga de todo esto. Al llamar a esto se evitará que su fragmento se destruya durante la rotación y sus solicitudes de red no se verán afectadas.
Puede que tenga que agregar este código para evitar que su diálogo se rechace en rotación, debido a un error con la biblioteca de compatibilidad:
@Override public void onDestroyView() { Dialog dialog = getDialog(); // handles https://code.google.com/p/android/issues/detail?id=17423 if (dialog != null && getRetainInstance()) { dialog.setDismissMessage(null); } super.onDestroyView(); }
Una de las ventajas de usar dialogFragment
comparación con sólo usar alertDialogBuilder
es exactamente porque dialogfragment puede automáticamente recrearse a sí mismo tras la rotación sin la intervención del usuario.
Sin embargo, cuando el fragmento de diálogo no se vuelve a crear, es posible que sobrescriba onSaveInstanceState
pero no para llamar a super
:
@Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); // <-- must call this if you want to retain dialogFragment upon rotation ... }
Este es un método de conveniencia que utiliza la corrección de la respuesta de antonyt:
public class RetainableDialogFragment extends DialogFragment { public RetainableDialogFragment() { setRetainInstance(true); } @Override public void onDestroyView() { Dialog dialog = getDialog(); // handles https://code.google.com/p/android/issues/detail?id=17423 if (dialog != null && getRetainInstance()) { dialog.setDismissMessage(null); } super.onDestroyView(); } }
Sólo deje que su DialogFragment
ampliar esta clase y todo estará bien. Esto se convierte especialmente útil, si tiene varios DialogFragments
en su proyecto que todos necesitan esta corrección.
- ¿Cómo puedo generar un apk que se pueda ejecutar sin servidor con react-native?
- Manera correcta de dar datos iniciales a los fragmentos?