How to save a Dialog Fragment through rotation?

I have a FragmentActivity that hosts the Dialog dialog box.

DialogFragment does network requests and handles Facebook authentication, so I need to save it during rotation.

I read all the other questions related to this problem, but none of them actually solved the problem.

I use putFragment and getFragment to save an instance of the fragment and get it again while re-creating the activity.

However, I always get a null pointer exception when calling getFragment on onRestoreInstanceState. I would also like to leave the dialog rejected during rotation, but so far I can’t even save an instance of it.

Any ideas what is going wrong?

This is what my code looks like:

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

This is the exception stack trace:

 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) 
+67
android android-fragments android-fragmentactivity android-dialogfragment
Feb 02 '13 at 0:58
source share
3 answers

Inside DialogFragment call Fragment.setRetainInstance(boolean) with true . You do not need to save the fragment manually, the structure will already take care of all this. Calling this will prevent the destruction of your fragment during rotation, and your network requests will not be affected.

You may need to add this code to stop the deviation of your dialog from turning due to an error with the compatibility library:

 @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(); } 
+131
Mar 16 '13 at 1:15
source share

One of the advantages of using dialogFragment over using only alertDialogBuilder is that the dialog alertDialogBuilder can automatically recreate itself when rotated without user intervention.

However, when the dialog onSaveInstanceState does not recreate itself, it is possible that you are overwriting onSaveInstanceState but not calling super :

 @Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); // <-- must call this if you want to retain dialogFragment upon rotation ... } 
+15
Sep 23 '13 at 8:13
source share

This is a convenience method using a fix from antonyt answer:

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

Just let your DialogFragment extend this class and everything will be fine. This is especially useful if there are several DialogFragments in your project that need this fix.

+8
May 28 '17 at 4:47 p.m.
source share



All Articles