android视图未连接到窗口管理器

android视图未连接到窗口管理器,android,exception,Android,Exception,我有以下一些例外情况: java.lang.IllegalArgumentException: View not attached to window manager at android.view.WindowManagerImpl.findViewLocked(WindowManagerImpl.java:355) at android.view.WindowManagerImpl.updateViewLayout(WindowManagerImpl.java:191) at android

我有以下一些例外情况:

java.lang.IllegalArgumentException: View not attached to window manager
at android.view.WindowManagerImpl.findViewLocked(WindowManagerImpl.java:355)
at android.view.WindowManagerImpl.updateViewLayout(WindowManagerImpl.java:191)
at android.view.Window$LocalWindowManager.updateViewLayout(Window.java:428)
at android.app.Dialog.onWindowAttributesChanged(Dialog.java:596)
at android.view.Window.setDefaultWindowFormat(Window.java:1013)
at com.android.internal.policy.impl.PhoneWindow.access$700(PhoneWindow.java:86)
at com.android.internal.policy.impl.PhoneWindow$DecorView.drawableChanged(PhoneWindow.java:1951)
at com.android.internal.policy.impl.PhoneWindow$DecorView.fitSystemWindows(PhoneWindow.java:1889)
at android.view.ViewRoot.performTraversals(ViewRoot.java:727)
at android.view.ViewRoot.handleMessage(ViewRoot.java:1633)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:123)
at android.app.ActivityThread.main(ActivityThread.java:4338)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:521)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:860)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618)
at dalvik.system.NativeStart.main(Native Method)
我在谷歌上搜索了一下,发现它与弹出窗口和打开屏幕有关,但没有提到我的代码

问题是:

  • 有办法找到答案吗 确切地说,这个问题是什么时候发生的 发生了什么
  • 除了转动屏幕,是否还有其他事件或操作触发此错误
  • 如何防止这种情况发生
  • 关于问题1):

    考虑到错误消息似乎没有说明是哪一行代码导致了问题,您可以使用断点来跟踪它。当程序到达特定的代码行时,断点暂停程序的执行。通过向关键位置添加断点,可以确定哪行代码导致崩溃。例如,如果您的程序在setContentView()行崩溃,您可以在那里设置断点。当程序运行时,它将在运行该行之前暂停。如果恢复导致程序在到达下一个断点之前崩溃,那么您就知道终止程序的那一行位于两个断点之间

    如果使用Eclipse,添加断点很容易。在代码左侧的空白处单击鼠标右键,然后选择“切换断点”。然后,您需要在调试模式下运行应用程序,该按钮看起来像正常运行按钮旁边的绿色昆虫。当程序到达断点时,Eclipse将切换到debug透视图,并向您显示它正在等待的行。要重新启动程序,请查找“恢复”按钮,该按钮看起来像正常的“播放”,但三角形左侧有一个垂直条

    您还可以用Log.d(“我的应用程序”,“这里的一些信息告诉您日志行在哪里”)填充您的应用程序,然后在Eclipse的LogCat窗口中发布消息。如果找不到该窗口,请使用窗口->显示视图->其他…->Android->LogCat


    希望有帮助

    我在该活动的清单中添加了以下内容

    android:configChanges="keyboardHidden|orientation|screenLayout"
    

    我遇到了这样一个问题:在屏幕方向发生变化时,活动在AsyncTask完成之前完成,进度对话框也完成了。我似乎通过将对话框设置为null
    onPause()
    来解决这个问题,然后在取消之前在AsyncTask中检查它

    @Override
    public void onPause() {
        super.onPause();
    
        if ((mDialog != null) && mDialog.isShowing())
            mDialog.dismiss();
        mDialog = null;
    }
    
    。。。在我的任务中:

    protected void onPreExecute() {
        mDialog = ProgressDialog.show(mContext, "", "Saving changes...",
                true);
    }
    
    protected void onPostExecute(Object result) {
       if ((mDialog != null) && mDialog.isShowing()) { 
            mDialog.dismiss();
       }
    }
    

    在清单中声明活动时,需要android:configChanges=“定向”

    例如:

    <activity android:theme="@android:style/Theme.Light.NoTitleBar" android:configChanges="orientation"  android:label="traducción" android:name=".PantallaTraductorAppActivity"></activity>
    
    
    
    或者只需添加

    protected void onPreExecute() {
        mDialog = ProgressDialog.show(mContext, "", "Saving changes...", true, false);
    }
    

    这将使
    ProgressDialog
    无法取消

    根据windowManager(链接)的代码,当您尝试更新的视图(可能属于对话框,但不是必需的)不再附加到窗口的实际根目录时,会发生这种情况

    正如其他人所建议的,在对对话框执行特殊操作之前,应该检查活动的状态

    以下是相关代码,这是问题的原因(复制自Android源代码):

    public void updateViewLayout(视图、ViewGroup.LayoutParams参数){
    如果(!(WindowManager的参数instanceof.LayoutParams)){
    抛出新的IllegalArgumentException(“参数必须是WindowManager.LayoutParams”);
    }
    最终WindowManager.LayoutParams wparams
    =(WindowManager.LayoutParams)参数;
    view.setLayoutParams(wparams);
    已同步(此){
    int index=findViewLocked(视图,true);
    ViewRootImpl root=mRoots[index];
    mParams[索引]=wparams;
    setLayoutParams(wparams,false);
    }
    }
    私有int findViewLocked(视图,需要布尔值){
    已同步(此){
    最终整数计数=mViews!=null?mViews.length:0;
    
    对于(int i=0;i我的问题是通过在我的android上锁定屏幕旋转来解决的。导致我出现问题的应用程序现在可以正常工作了

    另一个选项是在对话框通过覆盖onAttachedToWindow()连接到窗口之前不启动异步任务在对话框上,这样它总是可以被拒绝的。

    如果您有一个
    活动
    对象挂起,您可以使用
    isDestroyed()
    方法:

    Activity activity;
    
    // ...
    
    if (!activity.isDestroyed()) {
        // ...
    }
    

    如果您有一个非匿名的
    AsyncTask
    子类,可以在不同的地方使用它,这很好。

    我使用的是一个定制的静态类,它生成-显示和隐藏一个对话框。 这个类也被其他活动使用,而不仅仅是一个活动。 现在,你所描述的问题也出现在我的脑海中,我已经呆了一夜,想找到一个解决办法

    最后,我向您介绍解决方案

    如果您想显示或关闭对话框,但不知道是哪个活动启动了该对话框以便触摸它,则以下代码适用于您

     static class CustomDialog{
    
         public static void initDialog(){
             ...
             //init code
             ...
         }
    
          public static void showDialog(){
             ...
             //init code for show dialog
             ...
         }
    
         /****This is your Dismiss dialog code :D*******/
         public static void dismissProgressDialog(Context context) {                
                //Can't touch other View of other Activiy..
                //http://stackoverflow.com/questions/23458162/dismiss-progress-dialog-in-another-activity-android
                if ( (progressdialog != null) && progressdialog.isShowing()) {
    
                    //is it the same context from the caller ?
                    Log.w("ProgressDIalog dismiss", "the dialog is from"+progressdialog.getContext());
    
                    Class caller_context= context.getClass();
                    Activity call_Act = (Activity)context;
                    Class progress_context= progressdialog.getContext().getClass();
    
                    Boolean is_act= ( (progressdialog.getContext()) instanceof  Activity )?true:false;
                    Boolean is_ctw= ( (progressdialog.getContext()) instanceof  ContextThemeWrapper )?true:false;
    
                    if (is_ctw) {
                        ContextThemeWrapper cthw=(ContextThemeWrapper) progressdialog.getContext();
                        Boolean is_same_acivity_with_Caller= ((Activity)(cthw).getBaseContext() ==  call_Act )?true:false;
    
                        if (is_same_acivity_with_Caller){
                            progressdialog.dismiss();
                            progressdialog = null;
                        }
                        else {
                            Log.e("ProgressDIalog dismiss", "the dialog is NOT from the same context! Can't touch.."+((Activity)(cthw).getBaseContext()).getClass());
                            progressdialog = null;
                        }
                    }
    
    
                }
            } 
    
     }
    

    为什么不试试抓,像这样:

    protected void onPostExecute(Object result) {
            try {
                if ((mDialog != null) && mDialog.isShowing()) {
                    mDialog.dismiss();
                }
            } catch (Exception ex) {
                Log.e(TAG, ex.getMessage(), ex);
            }
        }
    

    在与这个问题进行斗争之后,我终于找到了以下解决方法:

    /**
     * Dismiss {@link ProgressDialog} with check for nullability and SDK version
     *
     * @param dialog instance of {@link ProgressDialog} to dismiss
     */
    public void dismissProgressDialog(ProgressDialog dialog) {
        if (dialog != null && dialog.isShowing()) {
    
                //get the Context object that was used to great the dialog
                Context context = ((ContextWrapper) dialog.getContext()).getBaseContext();
    
                // if the Context used here was an activity AND it hasn't been finished or destroyed
                // then dismiss it
                if (context instanceof Activity) {
    
                    // Api >=17
                    if (!((Activity) context).isFinishing() {
                        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
                            if (!((Activity) context).isDestroyed()) {
                                dismissWithExceptionHandling(dialog);
                            }
                        } else { 
                            // Api < 17. Unfortunately cannot check for isDestroyed()
                            dismissWithExceptionHandling(dialog);
                        }
                    }
                } else
                    // if the Context used wasn't an Activity, then dismiss it too
                    dismissWithExceptionHandling(dialog);
            }
            dialog = null;
        }
    }
    
    /**
     * Dismiss {@link ProgressDialog} with try catch
     *
     * @param dialog instance of {@link ProgressDialog} to dismiss
     */
    public void dismissWithExceptionHandling(ProgressDialog dialog) {
        try {
            dialog.dismiss();
        } catch (final IllegalArgumentException e) {
            // Do nothing.
        } catch (final Exception e) {
            // Do nothing.
        } finally {
            dialog = null;
        }
    }
    
    /**
    *关闭{@link ProgressDialog},检查是否为空以及SDK版本
    *
    *要关闭的{@link ProgressDialog}的@param dialog实例
    */
    public void dismissProgressDialog(ProgressDialog对话框){
    if(dialog!=null&&dialog.isShowing()){
    //获取用于创建对话框的上下文对象
    上下文=((ContextWrapper)dialog.getContext()).getBaseContext();
    //如果此处使用的上下文是一个活动,但尚未完成或销毁
    //那就驳回它吧
    if(活动的上下文实例){
    //Api>=17
    if(!((活动)上下文).isFinishing(){
    if(Build.VERSION.SDK\u INT>=Build.VERSION\u code.JELLY\u BEAN\u MR1){
    if(!((活动)上下文).isDestroyed()){
    dismissWithExceptionHandling(对话框);
    }
    }否则{
    //Api<17。很遗憾,无法检查isDestroyed()
    
    /**
     * Dismiss {@link ProgressDialog} with check for nullability and SDK version
     *
     * @param dialog instance of {@link ProgressDialog} to dismiss
     */
    public void dismissProgressDialog(ProgressDialog dialog) {
        if (dialog != null && dialog.isShowing()) {
    
                //get the Context object that was used to great the dialog
                Context context = ((ContextWrapper) dialog.getContext()).getBaseContext();
    
                // if the Context used here was an activity AND it hasn't been finished or destroyed
                // then dismiss it
                if (context instanceof Activity) {
    
                    // Api >=17
                    if (!((Activity) context).isFinishing() {
                        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
                            if (!((Activity) context).isDestroyed()) {
                                dismissWithExceptionHandling(dialog);
                            }
                        } else { 
                            // Api < 17. Unfortunately cannot check for isDestroyed()
                            dismissWithExceptionHandling(dialog);
                        }
                    }
                } else
                    // if the Context used wasn't an Activity, then dismiss it too
                    dismissWithExceptionHandling(dialog);
            }
            dialog = null;
        }
    }
    
    /**
     * Dismiss {@link ProgressDialog} with try catch
     *
     * @param dialog instance of {@link ProgressDialog} to dismiss
     */
    public void dismissWithExceptionHandling(ProgressDialog dialog) {
        try {
            dialog.dismiss();
        } catch (final IllegalArgumentException e) {
            // Do nothing.
        } catch (final Exception e) {
            // Do nothing.
        } finally {
            dialog = null;
        }
    }
    
    @Override
        protected void onDestroy() {
            if (progressDialog != null && progressDialog.isShowing())
                progressDialog.dismiss();
            super.onDestroy();
        }