1. 程式人生 > >java.lang.IllegalArgumentException: View=PhoneWindow$DecorView{...} not attached to window manager

java.lang.IllegalArgumentException: View=PhoneWindow$DecorView{...} not attached to window manager

針對此問題本文主要是丟擲解決方案,定義一個基類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,如果大家測試有問題歡迎提出,歡迎提出更好的解決方案^_^