java.lang.IllegalArgumentException: View=PhoneWindow$DecorView{...} not attached to window manager
阿新 • • 發佈:2019-01-27
針對此問題本文主要是丟擲解決方案,定義一個基類BaseDialog,其他Dialog繼承此基類,BaseDialog程式碼如下:
import android.app.Activity; import android.app.Dialog; import android.arch.lifecycle.Lifecycle; import android.arch.lifecycle.LifecycleObserver; import android.arch.lifecycle.OnLifecycleEvent; import android.content.Context; import android.support.annotation.NonNull; import android.support.v4.app.FragmentActivity; abstract public class BaseDialog extends Dialog implements LifecycleObserver { protected Context context; public BaseDialog(@NonNull Context context) { super(context); init(context); } public BaseDialog(@NonNull Context context, int themeResId) { super(context, themeResId); init(context); } private void init(Context context) { this.context = context; if (context instanceof FragmentActivity) { ((FragmentActivity) context).getLifecycle().addObserver(this); } } @Override public void dismiss() { if (context instanceof Activity) { Activity activity = (Activity) context; if (!activity.isFinishing()) { super.dismiss(); } } } @Override public void show() { if (context instanceof Activity) { Activity activity = (Activity) context; if (!activity.isFinishing()) { super.show(); } } } @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY) public void onDestroy() { if (isShowing()) { dismiss(); } } }
重現此錯誤我的方法是開啟設定,找到開發者選項下的不保留活動的選項,選擇開啟,截圖如下:
測試程式碼為:
public class DialogTestActivity extends AppCompatActivity { private SimpleDialog simpleDialog; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); simpleDialog=new SimpleDialog(this); simpleDialog.show(); new DialogThread().start(); } private class DialogThread extends Thread{ @Override public void run() { SystemClock.sleep(5000); simpleDialog.dismiss(); } } }
SimpleDialog程式碼為:
public class SimpleDialog extends Dialog { public SimpleDialog(@NonNull Context context) { super(context); setContentView(android.R.layout.simple_list_item_checked); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); } }
執行在手機上然後馬上按下Home鍵將應用退出後臺,此時重現此錯誤,列印的錯誤日誌資訊全文為:
11-05 10:52:04.407 23911-23911/com.midas.demo E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.midas.demo, PID: 23911
java.lang.IllegalArgumentException: View=com.android.internal.policy.impl.PhoneWindow$DecorView{41f587f8 V.E..... R.....I. 0,0-640,485} 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:350)
at android.app.Dialog$1.run(Dialog.java:126)
at android.os.Handler.handleCallback(Handler.java:733)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:5061)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:812)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:628)
at dalvik.system.NativeStart.main(Native Method)
從上面的日誌可以看出,是當dialog呼叫dismiss方法的時候引發的。
原因分析大概就是dialog所依附的activity已經銷燬,此時再呼叫dismiss就會發現沒有activity依附,所以就丟擲此異常。
1、在頁面的destory方法中,判斷dialog是否存在,若存在,dismiss就銷燬,使dialog的生命週期與activity同步;
2、在一些由於耗時操作或其他操作導致容易出現activity被銷燬而dialog未銷燬的地方,使用activity.isfinidhing方法判斷activity是否被銷燬,銷燬,則終止程式碼。
基於此解決方法的實現程式碼已在此文開始部分就提出,測試方法就是將上面提到的測試Dialog改成繼承自定義的BaseDialog,如果大家測試有問題歡迎提出,歡迎提出更好的解決方案^_^