Exception One,
java.lang.IllegalArgumentException: View not attached to window manager
at android.view.WindowManagerImpl.findViewLocked(WindowManagerImpl.java:664)
at android.view.WindowManagerImpl.removeView(WindowManagerImpl.java:354)
at android.view.WindowManagerImpl$CompatModeWrapper.removeView(WindowManagerImpl.java:165)
at android.app.Dialog.dismissDialog(Dialog.java:319)
at android.app.Dialog.dismiss(Dialog.java:302)
at com.android.email.activity.setup.AccountSetupBasics$FindProviderTask.onPostExecute(AccountSetupBasics.java:914)
at com.android.email.activity.setup.AccountSetupBasics$FindProviderTask.onPostExecute(AccountSetupBasics.java:863)
at android.os.AsyncTask.finish(AsyncTask.java:631)
at android.os.AsyncTask.access$600(AsyncTask.java:177)
at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:644)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4780)
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:808)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:575)
at dalvik.system.NativeStart.main(Native Method)
Exception Two,
STACK TRACE:
java.lang.IllegalArgumentException: View not attached to window manager
at android.view.WindowManagerImpl.findViewLocked(WindowManagerImpl.java:355)
at android.view.WindowManagerImpl.removeView(WindowManagerImpl.java:200)
at android.view.Window$LocalWindowManager.removeView(Window.java:432)
at android.app.Dialog.dismissDialog(Dialog.java:280)
at android.app.Dialog.access$000(Dialog.java:73)
at android.app.Dialog$1.run(Dialog.java:109)
at android.app.Dialog.dismiss(Dialog.java:264)
at com.xxxxxxxx.suquashi.ActionDialog.access$001(ActionDialog.java:43)
at com.xxxxxxxx.suquashi.ActionDialog$2.onAnimationEnd(ActionDialog.java:299)
at android.view.animation.AnimationSet.getTransformation(AnimationSet.java:329)
at android.view.ViewGroup.drawChild(ViewGroup.java:1494)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1356)
at android.view.ViewGroup.drawChild(ViewGroup.java:1627)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1356)
at android.view.ViewGroup.drawChild(ViewGroup.java:1627)
[Bad Design]
The following code is a bad design to put dialog.dismiss() and activity.finish() in the asynctask.
final AsyncTask<MyParams, Object, MyResult> task = new AsyncTask<MyParams, Object, MyResult>() { @Override protected MyResult doInBackground(MyParams... params) { // Long operation goes here } @Override protected void onPostExecute(MyResult result) { dialog.dismiss(); onCompletion(result); finish(); }};
First every dialog or sth extends dialog would have a own window and décor view(itself), and except popup(dialog) there is a window and décor view. Second when the phone change orientation, the activity Thread would call HandleRelaunchActivity(this would call handledestroyactivity), the window manager would remove all the window and décor view and then create new window and décor, so the old décor has no use after this had been done.
In the code of action dialog there would be a animation make the super dismiss called later, but if the HandleRelaunchActivity happened, the actiondialog's décor would be useless, then the animation call back come, the super dismiss is called, it should not be in the mview[] in windowmanagerimpl. After that analyze, I think if this happened, we don't have very useful method to prevent, and it should be ok for a not in the array, but if lockview method throw a exception, I think we could just catch it. It won't affect much because the décor view(actiondialog) would be useless.
Change affects the way the ActionDialog behaves when it is dismissed. Most notable for an end user is that an ActionDialog that is closed when its Activity is being shut down will no longer animate.
Addition to the information below The reason for the Dialog being removed from WindowManager in the first place is typically due to a rotation of the screen, and if the ActionDialog is managed the Android system will take care of removing/dismissing it.
The problem seems to be because ActionDialog delays Dialog.dismiss() to play an animation. When the animation is finished ActionDialog calls Dialog.dismiss but at that time it has already been removed from the WindowManager so the WindowManager will throw an exception when Dialog requests to be removed from WindowManager.
This problem is thus related to ActionDialog and not HomeScreen which means that other applications using ActionDialog could also get this problem. I have seen one MTBF-crash for com.sonyericsson.contacts and one for Timescape due to this.
It could be wrong here, but I suspect that multiple phones 'in the wild' have a bug that causes them to switch orientation on applications that are marked as statically oriented. This happens quite a bit on my personal phone, and on many of the test phones our group uses (including droid, n1, g1, hero). Typically an app marked as statically oriented (perhaps vertically) will lay itself out for a second or two using a horizontal orientation, and then immediately switch back. End result is that even though you don't want your app to switch orientation, you have to be prepared that it may. I don't know under what exact conditions this behavior can be reproduced, I don't know if it is specific to a version of Android. All I know is that I have seen it happen plenty of times
I would recommend using the solution provided in the link you posted that suggests overriding the Activity onCreateDialog method and letting the Android OS manage the lifecycle of your Dialogs. It looks to me like even though you don't want your activity to switch orientations, it is switching orientation somewhere. You can try to track down a method that will always prevent orientation switching, but I am trying to tell you that I personally don't believe there is a foolproof way that works on all current Android phones in the market.
[Dialog dismiss Framework Code]
301 public void dismiss() {302 if (Thread.currentThread() != mUiThread) {303 mHandler.post(mDismissAction);304 } else {305 mHandler.removeCallbacks(mDismissAction);306 mDismissAction.run();307 }308 }
For Exception One, In email, IllegalArgumentException rises in onPostExec when the AsyncTsk is finishing.
When dismissing the dialog, WindowManager can't find the window and view in its Views.
300 public void dismiss() {301 if (Looper.myLooper() == mHandler.getLooper()) {302 dismissDialog();303 } else {304 mHandler.post(mDismissAction);305 }306 }307308 void dismissDialog() {309 if (mDecor == null || !mShowing) {310 return;311 }312313 if (mWindow.isDestroyed()) {314 Log.e(TAG, "Tried to dismissDialog() but the Dialog's window was already destroyed!");315 return;316 }317318 try {319 mWindowManager.removeView(mDecor);320 } finally {321 if (mActionMode != null) {322 mActionMode.finish();323 }324 mDecor = null;325 mWindow.closeAllPanels();326 onStop();327 mShowing = false;328329 sendDismissMessage();330 }331 }158 @Override159 public void removeView(View view) {160 if(null == view)161 {162 Log.d("WindowManager", "uuNote:removeView:view=null###");163 throw new NullPointerException("view parameter is NULL into findViewLocked()");164 }165 mWindowManager.removeView(view);166 }352 public void removeView(View view) {353 synchronized (this) {354 int index = findViewLocked(view, true);355 View curView = removeViewLocked(index);356 if (curView == view) {357 return;358 }359360 throw new IllegalStateException("Calling with view " + view361 + " but the ViewAncestor is attached to " + curView);362 }363 }649 private int findViewLocked(View view, boolean required) {650 synchronized (this) {651 final int count = mViews != null ? mViews.length : 0;652 for (int i=0; i<count; i++) {653 if (mViews[i] == view) {654 return i;655 }656 }657 if(null==view)658 {659 Log.d("WindowManager", "findViewLocked:view=null###");660 required = false;661 throw new NullPointerException("view parameter is NULL into findViewLocked()");662 }663 if (required) {664 throw new IllegalArgumentException(665 "View not attached to window manager");666 }667 return -1;668 }669 }670}
[Reference Solution]
Move the dialog.dismiss() and activity.finish to UiThread.
new Thread() { 2946 @Override 2947 public void run() { 2948 Uri uri = ContentUris.withAppendedId(SemcThreads.CONTENT_URI, 2949 threadId); 2950 getContentResolver().delete(uri, null, null); 2951 runOnUiThread(new Runnable() { 2952 public void run() { 2953 pd.dismiss(); 2954 2955 // prevent saving of draft 2956 mComposer = null; 2957 mConversation = null; 2958 2959 Notifications.updateAll(ConversationActivity.this); 2960 ConversationCache.clear(); 2961 finish(); 2962 } 2963 }); 2964 } 2965 }.start();
if you use many dialogs, should close all dialog in activity's overriden onDestroy() or onStop().
then you may be able to reduce the frequency 'java.lang.IllegalArgumentException: View not attached to window manager' exception occurs.
@Overrideprotected void onDestroy() { Log.d(TAG, "called onDestroy"); mDialog.dismiss(); super.onDestroy();}
but little exceed...
to make it more clear, you prevent to show any dialog after onDestroy called.
i don't use as below. but it's clear.
private boolean mIsDestroyed = false;private void showDialog() { closeDialog(); if (mIsDestroyed) { Log.d(TAG, "called onDestroy() already."); return; } mDialog = new AlertDialog(this) .setTitle("title") .setMessage("This is DialogTest") .setNegativeButton("Cancel", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); } }) .create(); mDialog.show();}private void closeDialog() { if (mDialog != null && mDialog.isShowing()) { mDialog.dismiss(); }}@Overrideprotected void onDestroy() { Log.d(TAG, "called onDestroy"); mIsDestroyed = true; closeDialog(); super.onDestroy();}
And at last, is it better to use dialog.cancel() rather than dialog.dismiss()?