java.lang.IllegalArgumentException :보기가 창 관리자에 첨부되지 않았습니다 슬라이드로 다시 생성되지 않는다고 선언됩니다.

AsyncTask를 시작하고 작업 기간 동안 진행률 대화 상자를 표시하는 활동이 있습니다. 액티비티는 회전 또는 키보드 슬라이드로 다시 생성되지 않는다고 선언됩니다.

    <activity android:name=".MyActivity"
              android:label="@string/app_name"
              android:configChanges="keyboardHidden|orientation"
              >
        <intent-filter>
        </intent-filter>
    </activity>

작업이 완료되면 대화 상자가 닫히지 만 일부 전화 (프레임 워크 : 1.5, 1.6)에서는 이러한 오류가 발생합니다.

java.lang.IllegalArgumentException: View not attached to window manager
    at android.view.WindowManagerImpl.findViewLocked(WindowManagerImpl.java:356)
    at android.view.WindowManagerImpl.removeView(WindowManagerImpl.java:201)
    at android.view.Window$LocalWindowManager.removeView(Window.java:400)
    at android.app.Dialog.dismissDialog(Dialog.java:268)
    at android.app.Dialog.access$000(Dialog.java:69)
    at android.app.Dialog$1.run(Dialog.java:103)
    at android.app.Dialog.dismiss(Dialog.java:252)
    at xxx.onPostExecute(xxx$1.java:xxx)

내 코드는 다음과 같습니다

final Dialog dialog = new AlertDialog.Builder(context)
    .setTitle("Processing...")
    .setCancelable(true)
    .create();

final AsyncTask<MyParams, Object, MyResult> task = new AsyncTask<MyParams, Object, MyResult>() {

    @Override
    protected MyResult doInBackground(MyParams... params) {
        // Long operation goes here
    }

    @Override
    protected void onPostExecute(MyResult result) {
        dialog.dismiss();
        onCompletion(result);
    }
};

task.execute(...);

dialog.setOnCancelListener(new OnCancelListener() {
    @Override
    public void onCancel(DialogInterface arg0) {
        task.cancel(false);
    }
});

dialog.show();

내가 읽은 것 ( http://bend-ing.blogspot.com/2008/11/properly-handle-progress-dialog-in.html )에서 안드로이드 소스에서 본 것은 그것을 얻을 수있는 유일한 상황처럼 보입니다. 활동이 파괴 된 경우는 예외입니다. 그러나 내가 언급했듯이, 나는 기본 행사를위한 활동 레크리에이션을 금지합니다.

따라서 어떤 제안이라도 대단히 감사합니다.



답변

대화 상자를 닫고 onPostExecute 메소드에서 활동을 완료하면 때때로이 오류가 발생 합니다. 대화가 성공적으로 종료되기 전에 때때로 활동이 완료되는 것 같습니다.

나에게 효과적인 간단하면서도 효과적인 솔루션

@Override
protected void onPostExecute(MyResult result) {
    try {
        if ((this.mDialog != null) && this.mDialog.isShowing()) {
            this.mDialog.dismiss();
        }
    } catch (final IllegalArgumentException e) {
        // Handle or log or ignore
    } catch (final Exception e) {
        // Handle or log or ignore
    } finally {
        this.mDialog = null;
    }
}


답변

다음은이 주제에서 찾은 모든 정답 (@Damjan 및 @Kachi 덕분)을 정리 한 “글 머리표 증명”솔루션입니다. 여기서 다른 모든 탐지 방법이 성공하지 못한 경우에만 예외가 삼켜집니다. 필자의 경우 대화 상자를 자동으로 닫아야하며 이것이 앱 충돌을 방지하는 유일한 방법입니다. 도움이 되길 바랍니다. 의견이 있거나 더 나은 해결책이 있으면 투표하고 의견을 남겨주십시오. 감사합니다!

public void dismissWithCheck(Dialog dialog) {
        if (dialog != null) {
            if (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 (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
                        if (!((Activity) context).isFinishing() && !((Activity) context).isDestroyed()) {
                            dismissWithTryCatch(dialog);
                        }
                    } else {

                        // Api < 17. Unfortunately cannot check for isDestroyed()
                        if (!((Activity) context).isFinishing()) {
                            dismissWithTryCatch(dialog);
                        }
                    }
                } else
                    // if the Context used wasn't an Activity, then dismiss it too
                    dismissWithTryCatch(dialog);
            }
            dialog = null;
        }
    }

    public void dismissWithTryCatch(Dialog dialog) {
        try {
            dialog.dismiss();
        } catch (final IllegalArgumentException e) {
            // Do nothing.
        } catch (final Exception e) {
            // Do nothing.
        } finally {
            dialog = null;
        }
    }


답변

해결 방법이있을 수 있습니다.

같은 문제가 있었는데 (파일 시스템을 ListView통해 )을 통해 많은 항목을로드 하고 AsyncTask있습니다. 했던 onPreExecute()을 발사 ProgressDialog한 다음 모두 onPostExecute()onCancelled()(작업이를 통해 명시 적으로 취소 될 때 호출 AsyncTask.cancel()을 통해 폐쇄) .cancel().

onCancelled()메소드 에서 대화 상자를 죽일 때 동일한 “java.lang.IllegalArgumentException :보기가 창 관리자에 연결되지 않았습니다”오류가 발생 했습니다 AsyncTask(훌륭한 선반 응용 프로그램 에서이 작업을 보았습니다 ).

해결 방법은 다음 AsyncTask을 포함 하는 공개 필드를 만드는 것입니다 ProgressDialog.

public ProgressDialog mDialog;

그런 다음을 onDestroy()취소하면 다음을 AsyncTask통해 관련 대화 상자를 종료 할 수도 있습니다.

AsyncTask.mDialog.cancel();

에서 AsyncTask.cancel()DOES 트리거 onCancelled()를 호출 AsyncTask하지만 어떤 이유로 메소드가 호출 될 때보기가 이미 삭제되어 대화 상자를 취소하는 데 실패했습니다.


답변

이 문제를 해결하는 올바른 해결책은 다음과 같습니다.

public void hideProgress() {
    if(mProgressDialog != null) {
        if(mProgressDialog.isShowing()) { //check if dialog is showing.

            //get the Context object that was used to great the dialog
            Context context = ((ContextWrapper)mProgressDialog.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) {
                if(!((Activity)context).isFinishing() && !((Activity)context).isDestroyed())
                    mProgressDialog.dismiss();
            } else //if the Context used wasnt an Activity, then dismiss it too
                mProgressDialog.dismiss();
        }
        mProgressDialog = null;
    }
}

이 솔루션은 모든 예외를 맹목적으로 잡는 대신 문제의 근원을 해결합니다. 대화를 초기화하는 데 사용 된 활동이 이미 완료되었을 때 대화 상자를 닫으려고합니다. KitKat을 실행하는 Nexus 4에서 작업하지만 모든 버전의 Android에서 작동합니다.


답변

나는 ‘Damjan’의 의견에 동의합니다.
많은 대화 상자를 사용하는 경우 onDestroy () 또는 onStop ()에서 모든 대화 상자를 닫아야합니다.
그런 다음 빈도를 줄일 수 있습니다 ‘java.lang.IllegalArgumentException : 창 관리자에 첨부되지 않은보기’예외가 발생합니다.

@Override
protected void onDestroy() {
    Log.d(TAG, "called onDestroy");
    mDialog.dismiss();
    super.onDestroy();
}


더 명확하게하기 위해 onDestroy가 호출 된 후 대화 상자를 표시하지 않습니다.
나는 아래와 같이 사용하지 않는다. 그러나 분명하다.

private boolean mIsDestroyed = false;

private void showDialog() {
    closeDialog();

    if (mIsDestroyed) {
        Log.d(TAG, "called onDestroy() already.");
        return;
    }

    mDialog = new AlertDialog(this)
        .setTitle("title")
        .setMessage("This is DialogTest")
        .setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int which) {
                dialog.dismiss();
            }
        })
        .create();
    mDialog.show();
}

private void closeDialog() {
    if (mDialog != null) {
        mDialog.dismiss();
    }
}

@Override
protected void onDestroy() {
    Log.d(TAG, "called onDestroy");
    mIsDestroyed = true;
    closeDialog();
    super.onDestroy();
}

행운을 빕니다!


답변

이것을 사용하십시오.

if(_dialog!=null && _dialog.isShowing())
_dialog.dismiss();

답변

나는 같은 문제를 겪었다.

@Override
protected void onPostExecute(MyResult result) {
    try {
        if ((this.mDialog != null) && this.mDialog.isShowing()) {
            this.mDialog.dismiss();
        }
    } catch (final IllegalArgumentException e) {
        // Handle or log or ignore
    } catch (final Exception e) {
        // Handle or log or ignore
    } finally {
        this.mDialog = null;
    }
}