zoukankan      html  css  js  c++  java
  • Android中View not attached to window manager错误的解决办法

    HILINK在运行的时候,有时会出现界面弹框消失的时候,程序崩溃现象,LOG如下,

    FATAL EXCEPTION: main

    Process: com.huawei.mw, PID: 10185

    java.lang.IllegalArgumentException: View not attached to window manager

    at android.view.WindowManagerGlobal.findViewLocked(WindowManagerGlobal.java:389)

    at android.view.WindowManagerGlobal.removeView(WindowManagerGlobal.java:318)

    at android.view.WindowManagerImpl.removeViewImmediate(WindowManagerImpl.java:84)

    at android.app.Dialog.dismissDialog(Dialog.java:331)

    at android.app.Dialog.dismiss(Dialog.java:314)

    at com.huawei.mw.plugin.app.activity.AppManagerActivity$1.handleMessage(AppManagerActivity.java:171)

    at android.os.Handler.dispatchMessage(Handler.java:98)

    at android.os.Looper.loop(Looper.java:157)

    at android.app.ActivityThread.main(ActivityThread.java:5356)

    原因是当Dialog调用dismiss方法的时候,WindowManager检查发现Dialog所属的Activity因为某种原因已经被杀掉,在依赖的activity上removeView的时候就会报上面的异常。

    Android源码如下

    void dismissDialog() {

            if (mDecor == null || !mShowing) {

                return;

            }

            if (mWindow.isDestroyed()) {

                return;

            }

            try {

                //此时Dialog所依赖的activity已经销毁,执行到此句就会出现崩溃

                mWindowManager.removeViewImmediate(mDecor);

            }  

            。。。。。。

    。。。。。。 

    }

    修改此问题的第一个方法是,在调用dialog.dismiss()的是时候对当前的activity进行判断,如果isfinish为true则不调用dialog.dismiss(),在activity的onDestroy()中对弹框资源回收。

    重点介绍第二种方法:Activity有相应的操作对话框的回调,比如showDialog,onCreateDialog(),dimissDialog(),removeDialog()等等,这些都是Activity的方法,用起来比较方便,一切都由框架操作,相对来说比较安全。

    另外就是一定要让对话框对象在Activity的可控制范围之内和生命周期之内,比如一定要是它的成员变量,并且在让对话框变量活跃在Activity的onCreate()和onDestroy()之间。

    举个简单的例子如下:

    Class DemoDialog {

    final int DIALOG_ID = 0;

    private Dialog demoDialog;

    @Override

    public void onCreate(Bundle savedInstanceState)
        {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main);
            Button button = (Button) this.findViewById(R.id.Button01);
            button.setOnClickListener (new View.OnClickListener()

            {

                @Override 

                public void onClick(View v)

               {

                  showDialog(final int DIALOG_ID);                  

               }

            }); 

    }      
           @Override
        public Dialog onCreateDialog(int id)
        {
            if(id == DIALOG_ID)
            {

    demoDialog = new ProgressDialog(this);
    demoDialog.setTitle(R.string.title);//设置标题

    demoDialog.setCancelable(false);      

      }       
            return demoDialog;
        }  

    Android SDK 源代码如下:

    public final void showDialog(int id) {
        showDialog(id, null);
    }
    public final boolean showDialog(int id, Bundle args) {
        if (mManagedDialogs == null) {
            mManagedDialogs = new SparseArray<ManagedDialog>();
        }
        ManagedDialog md = mManagedDialogs.get(id);
        if (md == null) {
            md = new ManagedDialog();
                     md.mDialog = createDialog(id, null, args);
            if (md.mDialog == null) {
                return false;
            }
            mManagedDialogs.put(id, md);
        }
        md.mArgs = args;
        onPrepareDialog(id, md.mDialog, args);
        md.mDialog.show();
        return true;

    }

    private Dialog createDialog(Integer dialogId, Bundle state, Bundle args) {
        final Dialog dialog = onCreateDialog(dialogId, args);
        if (dialog == null) {
            return null;
        }
        dialog.dispatchOnCreate(state);
        return dialog;
    }

    由上面的代码可以看出,我们自己创建的demoDialog的对象引用值传递给了Activity中自带的md.mDialog变量,当Activity销毁的时候,会调用onDestroy方法,android源码如下:

    protected void onDestroy() {

    if (DEBUG_LIFECYCLE) Slog.v(TAG, "onDestroy " + this);

            mCalled = true;

            // dismiss any dialogs we are managing.

            if (mManagedDialogs != null) {

                final int numDialogs = mManagedDialogs.size();

                for (int i = 0; i < numDialogs; i++) {

                    final ManagedDialog md = mManagedDialogs.valueAt(i);

                    if (md.mDialog.isShowing()) {

    /*当activity销毁的时候,因为demoDialog和md.mDialog指向内存中的同一对象,此时demoDialog也会在当前的activity中dismiss()掉,当前弹框的isShowing值变为false*/

                        md.mDialog.dismiss();

                    }

                }

                mManagedDialogs = null;

            }

    }

    我们回过头来看之前的dismissDialog()函数

    void dismissDialog() {

        /*当弹框在activity中自带的onDestroy中dimiss后,mShowing为false,如果开发人员再次调用demoDialog.dimiss()方法的时候直接return,就不会出现之前的崩溃问题。*/

            if (mDecor == null || !mShowing) {

                return;

            }

            。。。。。。

    。。。。。。 

    }

  • 相关阅读:
    rsync 服务器配置过程
    百度基础技术总结
    利用cobbler无人值守批量安装centos
    安装批量装机工具cobbler过程
    面试题
    JS作用域
    原型链
    ES6优缺点
    PostCSS理解与运用
    置换元素和非置换元素
  • 原文地址:https://www.cnblogs.com/zhangkefan/p/4479533.html
Copyright © 2011-2022 走看看