java.lang.IllegalArgumentException: View not attached to window manager when dismissing dialog
11919 단어 exception
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 }
307
308 void dismissDialog() {
309 if (mDecor == null || !mShowing) {
310 return;
311 }
312
313 if (mWindow.isDestroyed()) {
314 Log.e(TAG, "Tried to dismissDialog() but the Dialog's window was already destroyed!");
315 return;
316 }
317
318 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;
328
329 sendDismissMessage();
330 }
331 }
158 @Override
159 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 }
359
360 throw new IllegalStateException("Calling with view " + view
361 + " 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.
@Override
protected 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();
}
}
@Override
protected 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()?
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Exception Class에서 에러 코드 해석 ~초기초편~직장에서 C# 프로젝트가 내뿜는 오류 코드를 구문 분석하고 오류의 위치를 확인하기 위해 Exception class를 활용할 수 있었습니다. 지금까지 Exception Class 에 대해서 별로 파악할 수 없었기 때...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.