open full from custom activity android android-fragments android-fragmentactivity android-dialogfragment

android - full - open dialog fragment from activity



Cómo retener correctamente un DialogFragment a través de la rotación? (3)

Dentro de su DialogFragment , llame a Fragment.setRetainInstance(boolean) con el valor true . No es necesario guardar el fragmento manualmente, el marco ya se ocupa de todo esto. Llamar a esto evitará que su fragmento se destruya durante la rotación y sus solicitudes de red no se verán afectadas.

Es posible que deba agregar este código para evitar que su diálogo se descarte en la rotación, debido a un bug 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(); }

Tengo una FragmentActivity que alberga un DialogFragment.

DialogFragment realiza solicitudes de red y maneja la autenticación de Facebook, por lo que debo conservarla durante la rotación.

He leído todas las demás preguntas relacionadas con este tema, pero ninguna de ellas ha resuelto el problema.

Estoy usando putFragment y getFragment para guardar la instancia de 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 evitar que se descarte el diálogo durante la rotación, pero hasta ahora no puedo retener la instancia.

Alguna idea de lo que va mal?

Así es como se ve mi código 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); } }

Esta es la traza de pila de excepción:

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)


Este es un método práctico que utiliza la solució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(); } }

Solo deja que tu DialogFragment extienda esta clase y todo estará bien. Esto resulta especialmente útil si tiene múltiples DialogFragments en su proyecto que necesitan esta solución.


Una de las ventajas de usar dialogFragment comparación con el uso de alertDialogBuilder es exactamente porque el fragmento de diálogo puede recrearse automáticamente al girar sin intervención del usuario.

Sin embargo, cuando el fragmento de diálogo no se recrea a sí mismo, es posible que sobrescriba onSaveInstanceState pero no llame a super :

@Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); // <-- must call this if you want to retain dialogFragment upon rotation ... }