最近開始對APP上的Crash進行對應,發現有好多常見的問題,同一個問題在多個APP都相似的出現了,這裏記錄下這些常見的錯誤。css
crash log:html
java.lang.IllegalArgumentException: View=com.android.internal.policy.impl.PhoneWindow$DecorView{29b8ae38 V.E..... R.....I. 0,0-1160,607} not attached to window manager
at android.view.WindowManagerGlobal.findViewLocked(WindowManagerGlobal.java:370)
at android.view.WindowManagerGlobal.removeView(WindowManagerGlobal.java:299)
at android.view.WindowManagerImpl.removeViewImmediate(WindowManagerImpl.java:84)
at android.app.Dialog.dismissDialog(Dialog.java:329)
at android.app.Dialog.dismiss(Dialog.java:312)
設備信息:系統版本:4.4.2
根據錯誤log能夠看出基本又是在Activity的生命週期上出現的問題,Activity已經銷燬了,再調用Dialog.dismiss()方法。
通過代碼排查,定位到了問題:java
handler.postDelayed(dismissDialogRunnable,1000);
在Activity已經finish了,延遲1s後執行dismissDialogRunnable內對Dialog進行銷燬。
知道問題了,就很好解決了,取消延遲,在Activity的OnDestory方法中銷燬Dialog。
追根究底,下載了對應系統的的源碼查看:
首先:Dialog.dismiss()方法:
android
在dismissDialog方法中調用了WindowManager的removeViewImmediate方法:sql
@Override
public void removeViewImmediate(View view) {
mGlobal.removeView(view, true);
}
mGlobal是WindowManagerGlobal實例對象,繼續深刻:markdown
public void removeView(View view, boolean immediate) {
if (view == null) {
throw new IllegalArgumentException("view must not be null");
}
synchronized (mLock) {
int index = findViewLocked(view, true);
View curView = mRoots.get(index).getView();
removeViewLocked(index, immediate);
if (curView == view) {
return;
}
throw new IllegalStateException("Calling with view " + view
+ " but the ViewAncestor is attached to " + curView);
}
}
private int findViewLocked(View view, boolean required) {
final int index = mViews.indexOf(view);
if (required && index < 0) {
throw new IllegalArgumentException("View=" + view + " not attached to window manager");
}
return index;
}
在WindowManagerGlobal.findViewLocked中,會獲取Dialog所在Window.decorView的位置,若是獲取不到,則拋出異常。
至此,該問題發生的緣由已經很是明瞭了。app
其中部份內容參照:http://www.cnblogs.com/reverie/p/4846958.htmlide