Yes, I've read the countless questions regarding the very same problem.
My code is simple: I just use showDialog(int id)
on the onCreate
, and then I rotate the device. The code is just that (test case), and that's enough to cause the problem. It was my understanding that showDialog
's methods would take care of that... the dialog would disappear and then the onCreate
would be called later after the change and show the dialog again, cleanly. But no. What's wrong with this reasoning?
I (think I) understand the cause, but I don't know how to solve that. Even the iosched app has the same problem with their implementation of the EULA window (change orientation on the eula dialog and you get the leak). I've read about dismissing the dialog on onPause, but 1) I risk dismissing when it's not shown already, and 2) tracking the dialog seems too much work. There must be a more robust approach.
So... what's the cleaner code that is needed to handle that?
Thank you.
Log error output:
01-30 00:27:18.615: E/WindowManager(20316): Activity com.test.PreSetupActivity has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView@418e0c28 that was originally added here
01-30 00:27:18.615: E/WindowManager(20316): android.view.WindowLeaked: Activity com.test.PreSetupActivity has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView@418e0c28 that was originally added here
01-30 00:27:18.615: E/WindowManager(20316): at android.view.ViewRootImpl.<init>(ViewRootImpl.java:343)
01-30 00:27:18.615: E/WindowManager(20316): at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:245)
01-30 00:27:18.615: E/WindowManager(20316): at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:193)
01-30 00:27:18.615: E/WindowManager(20316): at android.view.WindowManagerImpl$CompatModeWrapper.addView(WindowManagerImpl.java:118)
01-30 00:27:18.615: E/WindowManager(20316): at android.view.Window$LocalWindowManager.addView(Window.java:537)
01-30 00:27:18.615: E/WindowManager(20316): at android.app.Dialog.show(Dialog.java:274)
01-30 00:27:18.615: E/WindowManager(20316): at com.test.PreSetupActivity.onCreate(PreSetupActivity.java:88)
01-30 00:27:18.615: E/WindowManager(20316): at android.app.Activity.performCreate(Activity.java:4465)
01-30 00:27:18.615: E/WindowManager(20316): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1049)
01-30 00:27:18.615: E/WindowManager(20316): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1919)
01-30 00:27:18.615: E/WindowManager(20316): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1980)
01-30 00:27:18.615: E/WindowManager(20316): at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:3347)
01-30 00:27:18.615: E/WindowManager(20316): at android.app.ActivityThread.access$700(ActivityThread.java:122)
01-30 00:27:18.615: E/WindowManager(20316): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1150)
01-30 00:27:18.615: E/WindowManager(20316): at android.os.Handler.dispatchMessage(Handler.java:99)
01-30 00:27:18.615: E/WindowManager(20316): at android.os.Looper.loop(Looper.java:137)
01-30 00:27:18.615: E/WindowManager(20316): at android.app.ActivityThread.main(ActivityThread.java:4340)
01-30 00:27:18.615: E/WindowManager(20316): at java.lang.reflect.Method.invokeNative(Native Method)
01-30 00:27:18.615: E/WindowManager(20316): at java.lang.reflect.Method.invoke(Method.java:511)
01-30 00:27:18.615: E/WindowManager(20316): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
01-30 00:27:18.615: E/WindowManager(20316): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
01-30 00:27:18.615: E/WindowManager(20316): at dalvik.system.NativeStart.main(Native Method)
Have an inner class which acts as your stateholder and have a boolean field in there which indicates whether or not your dialog is showing. Keep track of this across orientation changes using onRetainNonConfigurationInstance
and just re-show the dialog on onResume
Here is some code+pseudo-code:
public class ProfileActivity extends Activity {
private StateHolder mStateHolder;
private Dialog dialog;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Object retained = getLastNonConfigurationInstance();
if (retained != null && retained instanceof StateHolder) {
mStateHolder = (StateHolder) retained;
} else {
mStateHolder = new StateHolder();
}
}
@Override
public Object onRetainNonConfigurationInstance() {
return mStateHolder;
}
@Override
public void onPause() {
super.onPause();
if(dialog != null && dialog.isShowing()) {
dialog.dismiss();
}
}
@Override
public void onResume() {
if(mStateHolder.mIsShowingDialog) {
dialog.show();
}
}
private void showDialog() {
mStateHolder.mIsShowingDialog = true;
dialog.show();
}
private static class StateHolder {
boolean mIsShowingDialog;
public StateHolder() {}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With