programing

활동에서 원래 추가된 창이 누출되었습니다.

golfzon 2023. 6. 23. 23:53
반응형

활동에서 원래 추가된 창이 누출되었습니다.

이 오류는 무엇이며, 왜 발생합니까?

05-17 18:24:57.069: ERROR/WindowManager(18850): Activity com.mypkg.myP has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView@44c46ff0 that was originally added here
05-17 18:24:57.069: ERROR/WindowManager(18850): android.view.WindowLeaked: Activity ccom.mypkg.myP has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView@44c46ff0 that was originally added here
05-17 18:24:57.069: ERROR/WindowManager(18850):     at android.view.ViewRoot.<init>(ViewRoot.java:231)
05-17 18:24:57.069: ERROR/WindowManager(18850):     at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:148)
05-17 18:24:57.069: ERROR/WindowManager(18850):     at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:91)
05-17 18:24:57.069: ERROR/WindowManager(18850):     at android.view.Window$LocalWindowManager.addView(Window.java:424)
05-17 18:24:57.069: ERROR/WindowManager(18850):     at android.app.Dialog.show(Dialog.java:239)
05-17 18:24:57.069: ERROR/WindowManager(18850):     at com.mypkg.myP$PreparePairingLinkageData.onPreExecute(viewP.java:183)
05-17 18:24:57.069: ERROR/WindowManager(18850):     at android.os.AsyncTask.execute(AsyncTask.java:391)
05-17 18:24:57.069: ERROR/WindowManager(18850):     at com.mypkg.myP.onCreate(viewP.java:94)
05-17 18:24:57.069: ERROR/WindowManager(18850):     at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
05-17 18:24:57.069: ERROR/WindowManager(18850):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2544)
05-17 18:24:57.069: ERROR/WindowManager(18850):     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2621)
05-17 18:24:57.069: ERROR/WindowManager(18850):     at android.app.ActivityThread.access$2200(ActivityThread.java:126)
05-17 18:24:57.069: ERROR/WindowManager(18850):     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1932)
05-17 18:24:57.069: ERROR/WindowManager(18850):     at android.os.Handler.dispatchMessage(Handler.java:99)
05-17 18:24:57.069: ERROR/WindowManager(18850):     at android.os.Looper.loop(Looper.java:123)
05-17 18:24:57.069: ERROR/WindowManager(18850):     at android.app.ActivityThread.main(ActivityThread.java:4595)
05-17 18:24:57.069: ERROR/WindowManager(18850):     at java.lang.reflect.Method.invokeNative(Native Method)
05-17 18:24:57.069: ERROR/WindowManager(18850):     at java.lang.reflect.Method.invoke(Method.java:521)
05-17 18:24:57.069: ERROR/WindowManager(18850):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:860)
05-17 18:24:57.069: ERROR/WindowManager(18850):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618)
05-17 18:24:57.069: ERROR/WindowManager(18850):     at dalvik.system.NativeStart.main(Native Method)

활동을 종료한 후 대화상자를 표시하려고 합니다.

[편집]

이 질문은 구글에서 안드로이드 개발자를 위한 최고의 검색 중 하나이므로, 댓글에서 중요한 포인트를 몇 개 추가하는 것은 댓글 대화에 깊이 들어가지 않고 미래의 조사자에게 더 도움이 될 수 있습니다.

답변 1:

활동을 종료한 후 대화상자를 표시하려고 합니다.

정답 2

이 오류는 상황에 따라 약간 오해를 불러일으킬 수 있습니다(답이 여전히 정확하지만). 즉, 비동기 작업에서 처리되지 않은 예외가 던져져 활동이 종료된 후 진행률 대화 상자가 열려 이 예외가 발생했습니다.그래서 '진짜' 예외는 로그에서 조금 더 빨랐습니다.

정답 3

활동을 종료하기 전에 작성한 Dialog 인스턴스(예: Pause() 또는 Destroy()에서 해제() 호출

은 해책은전것다입니는하화결다것라고 부르는 것입니다.dismiss()에서.Dialog사용자가 생성한 위치viewP.java:183를종기전에하를 Activity예를 들어onPause() .든모.Window스앤Dialog는 s를 떠나기 .Activity.

사중인경우를 .AsyncTask아마도 그 로그 메시지는 기만적일 수 있습니다.당신이 당신의 로그에서 찾아보면, 당신은 아마도 당신의 로그에서 하나의 다른 오류를 발견할 수 있습니다.doInBackground()의 의방의 AsyncTask그것이 당신의 전류를 만들고 있습니다.Activity발하기위해한, 서번은그래폭▁the,▁to▁up번은▁blow한,해위▁and▁once.AsyncTask다시 돌아옵니다..음, 당신은 나머지를 알고 있습니다.은 이미 설명했습니다 :-) ㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅠ

실수로 전화를 걸어 이 오류를 트리거했습니다.hide()dismiss()AlertDialog.

를 들어) 실수로 (으)ㄹ 수도 있고, (으)ㄹ 수도 있고/ㄹ 수도 있는 전화를.finish()을 전시한 후에.AlertDialog스위치 문에서 중단 통화 문을 놓친 경우...

   @Override
   public void onClick(View v) {
    switch (v.getId()) {
        case R.id.new_button:
            openMyAlertDialog();
            break; <-- If you forget this the finish() method below 
                       will be called while the dialog is showing!
        case R.id.exit_button:
            finish();
            break;
        }
    }

finish()는 을 닫습니다.Activity 러나그나AlertDialog계속 표시 중입니다!

그래서 여러분이 나쁜 스레드화 문제나 복잡한 코딩 등을 찾기 위해 코드를 열심히 들여다보고 있을 때, 나무들을 위해 숲을 놓치지 마세요.때때로 그것은 누락된 브레이크 문처럼 단순하고 멍청한 것일 수 있습니다.:)

이 질문에 대한 답은 모두 맞았지만, 제가 실제로 왜 그런지 이해하기에는 약간 혼란스러웠습니다.약 2시간 동안 장난을 치다가 (저의 경우) 이 오류의 이유가 저를 덮쳤습니다.

다른 답변을 읽어보면 이미 알고 있듯이, 그는X has leaked window DecorView@d9e6131[]닫혔을 때 가 열려 것을 합니다. error는 앱이 닫혔다는 것을 의미합니다.하지만 왜 그랬을까?

대화 상자가 열려 있는 동안 다른 이유로 인해 앱이 손상되었을 수 있습니다.

이로 인해 코드의 버그로 인해 앱이 닫히고 다른 오류로 인해 앱이 닫히는 동시에 대화 상자가 열린 상태로 유지됩니다.

논리적으로 생각해 보세요.첫 번째 오류를 해결하면 두 번째 오류가 자동으로enter image description here 해결됩니다.

하나의 오류로 인해 다른 오류가 발생하고, 이로 인해 DOMIMINOS와 같은 다른 오류가 발생합니다!

이 문제는 활동을 종료한 후 대화상자를 표시할 때 발생합니다.

저는 단지 다음 코드를 적는 것만으로 이 문제를 해결했습니다.

@Override
public void onDestroy(){
    super.onDestroy();
    if ( progressDialog!=null && progressDialog.isShowing() ){
        progressDialog.cancel();
    }
}

기본적으로 progressDialog를 시작한 클래스에서 Destroy 메서드를 재정의하고 이 방법을 수행합니다."활동 창이 누출되었습니다" 문제를 해결했습니다.

저는 최근에 같은 문제에 직면했습니다.

이 문제의 배경은 대화 상자가 해제되기 전에 활동이 닫혔기 때문입니다.위와 같은 일이 일어나는 데는 여러 가지 이유가 있습니다.위의 게시물에 언급된 것들도 맞습니다.

저는 어떤 상황에 빠졌습니다. 스레드에서 예외를 던지는 함수를 호출했기 때문입니다.그 때문에 창문이 제거되었고 따라서 예외가 되었습니다.

이게 도움이 될 수도 있어요.

if (! isFinishing()) {

    dialog.show();

    }

활동이 삭제될 때 대화 상자 닫기

@Override
protected void onDestroy()
{
    super.onDestroy();
    if (pDialog!=null && pDialog.isShowing()){
        pDialog.dismiss();
    }
}

저는 동일한 모호한 오류 메시지를 가지고 있었고 그 이유를 전혀 몰랐습니다.이전 답변의 힌트를 바탕으로 GUI가 아닌 호출을 mDialog로 변경했습니다.finish()를 지정하면 mDialog.dismiss()가 되고 오류가 사라집니다.이것은 위젯의 동작에 영향을 미치지 않았지만 당황스러웠고 중요한 메모리 누수를 플래그로 표시했을 수 있습니다.

이 로그들을 비디오 플레이어 애플리케이션에 저장하고 있었습니다.이 메시지는 비디오 플레이어가 닫힌 동안 던져졌습니다.흥미롭게도, 저는 이 로그들을 무작위로 몇 번의 실행에 한 번씩 얻곤 했습니다. 또한내애이은어것않관습다니지여하에도떤션케플리▁any▁ination▁does▁involve▁not▁also다와 관련이 없습니다.progressdialog마지막으로 아래 구현을 통해 이 문제를 해결했습니다.

@Override
protected void onPause()
{
    Log.v("MediaVideo", "onPause");
    super.onPause();
    this.mVideoView.pause();
    this.mVideoView.setVisibility(View.GONE);
}

@Override
protected void onDestroy()
{
    Log.v("MediaVideo", "onDestroy");
    super.onDestroy();
}

@Override
protected void onResume()
{
    Log.v("MediaVideo", "onResume");
    super.onResume();
    this.mVideoView.resume();
}

를 합니다.OnPause에 전화를 걸어.mVideoView.pause() 세트 리고세트그세.visibilityGONE이런 식으로 나는 "를 해결할 수 있었습니다.Activity has leaked window로그 오류 문제입니다.

저도 같은 문제를 겪고 있었고 이 페이지를 찾았고, 제 상황이 다른 동안 저는 전화를 했습니다.finish에서.if경고 상자를 정의하기 전에 차단합니다.

그서래, 단히전기하화간기▁calling▁so전하화.dismiss(아직 만들어지지 않았기 때문에) 작동하지 않을 것입니다. 하지만 알렉스 볼보이의 대답을 읽고 그것이 경보 상자 때문이라는 것을 깨달은 후에.저는 그 안에 마무리 직후에 리턴 스테이트먼트를 추가하려고 했습니다.if차단하고 문제를 해결했습니다.

일단 마무리를 부르시면 모든 걸 멈추고 바로 끝나는 줄 알았는데, 그렇지가 않네요.그것은 코드 블록의 끝까지 가서 끝나는 것처럼 보입니다.

따라서 코드를 수행하기 전에 완료되는 상황을 구현하려면 완료 후 즉시 반환문을 작성해야 합니다. 그렇지 않으면 종료가 계속되고 종료가 코드 블록의 끝에서 호출된 것처럼 행동합니다.그래서 제가 이상한 오류를 범하게 된 것입니다.

private picked(File aDirectory){
     if(aDirectory.length()==0){
        setResult(RESULT_CANCELED, new Intent()); 
        finish(); 
        return;
    }
     AlertDialog.Builder alert= new AlertDialog.Builder(this); // Start dialog builder
     alert
        .setTitle("Question")
        .setMessage("Do you want to open that file?"+aDirectory.getName());
    alert
        .setPositiveButton("OK", okButtonListener)
        .setNegativeButton("Cancel", cancelButtonListener);
    alert.show();
}

내가 마무리를 부른 후 바로 리턴을 넣지 않으면, 그것은 마치 당신이 끝난 후에 그것을 부른 것처럼 행동할 것입니다.alert.show();따라서 대화 상자를 표시한 직후에 완료하여 창이 유출되었다고 말할 수 있습니다. 그렇지는 않지만 여전히 그렇다고 생각합니다.

완료 명령이 실행된 것과 다르게 작동한다는 것을 보여주기 때문에 여기에 추가하려고 생각했습니다. 그리고 제가 발견하기 전에 저와 같은 생각을 하는 다른 사람들이 있을 것입니다.

일반적으로 이 문제는 진행률 대화 상자로 인해 발생합니다. 활동에서 다음 방법 중 하나를 사용하여 이 문제를 해결할 수 있습니다.

 // 1):
          @Override
                protected void onPause() {
                    super.onPause();
                    if ( yourProgressDialog!=null && yourProgressDialog.isShowing() )
                  {
                        yourProgressDialog.cancel();
                    }
                }

       // 2) :
         @Override
            protected void onDestroy() {
                super.onDestroy();
                if ( yourProgressDialog!=null && yourProgressDialog.isShowing()
               {
                    yourProgressDialog.cancel();
                }
            }

다음은 AlertDialog를 해제하고 내부 활동에서 AlertDialog에 대한 참조를 유지하지 않으려는 경우의 해결 방법입니다.

솔루션을 사용하려면 프로젝트에 안드로이드x.dll 종속성이 있어야 합니다(댓글을 쓰는 순간에는 일반적인 요구 사항이라고 생각합니다).

이렇게 하면 대화 상자의 해제를 외부 개체(사용자)에 위임할 수 있으며, 작업이 종료될 때 자동으로 등록되기 때문에 더 이상 신경 쓸 필요가 없습니다.(여기 증거가 있습니다: https://github.com/googlecodelabs/android-lifecycles/issues/5) .

그래서 관찰자는 대화에 대한 참조를 유지하고, 활동은 관찰자에 대한 참조를 유지합니다."일시 중지"가 발생할 때 - 관찰자가 대화 상자를 해제하고, "파괴"가 발생할 때 - 활동이 관찰자를 제거하므로 누출이 발생하지 않습니다(글쎄요, 적어도 더 이상 logcat에서 오류가 보이지 않습니다).

// observer
class DialogDismissLifecycleObserver( private var dialog: AlertDialog? ) : LifecycleObserver {
    @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
    fun onPause() {
        dialog?.dismiss()
        dialog = null
    }
}
// activity code
private fun showDialog() {
        if( isDestroyed || isFinishing ) return
        val dialog = AlertDialog
            .Builder(this, R.style.DialogTheme)
            // dialog setup skipped
            .create()
        lifecycle.addObserver( DialogDismissLifecycleObserver( dialog ) )
        dialog.show()
}

이것은 질문에 대한 답은 아니지만 주제와 관련이 있습니다.

활동이 매니페스트에서 속성을 정의한 경우

 android:noHistory="true"

Pause()에서 실행한 후 활동 컨텍스트가 손실됩니다.따라서 이 컨텍스트를 사용하는 모든 보기에서 이 오류가 발생할 수 있습니다.

이 코드를 사용해 보십시오.

public class Sample extends Activity(){
@Override
 public void onCreate(Bundle instance){

}
 @Override
    public void onStop() {
        super.onStop();
      progressdialog.dismiss(); // try this
    }

}

경고를 표시할 뿐만 아니라 특정 활동 인스턴스를 완료하고 새 활동/서비스를 시작하거나 중지하려고 할 때도 경고가 호출될 수 있습니다.

예:

OldActivity instance;

    oncreate() {
       instance=this;
    }
    instance.finish();
    instance.startActivity(new Intent(ACTION_MAIN).setClass(instance, NewActivity.class));

진행률 대화 상자가 계속 표시되었을 때 활동을 완료하는 데 문제가 발생했습니다.

먼저 대화상자를 숨긴 다음 활동을 완료합니다.

이 다음시간오있수있다습니경우에 가 있을 때 할 수 .doInBackground()기능하고 이 코드를 가집니다.

마지막으로 대화 상자를 추가합니다.하고 수정합니다.doInBackground()를 수행

protected void onPreExecute() {
     super.onPreExecute();
     pDialog = new ProgressDialog(CreateAccount.this);
     pDialog.setMessage("Creating Product..");
     pDialog.setIndeterminate(false);
     pDialog.setCancelable(true);
     pDialog.show();

 }

 protected String doInBackground(String...args) {
     ERROR CAN BE IS HERE
 }

 protected void onPostExecute(String file_url) {
     // dismiss the dialog once done
     pDialog.dismiss();

이것은 내가 사용할 때 발생했습니다.ProgressDialogAsyncTask실제로 사용하고 있습니다.hide().onPostExecute@으로 @Alex Volovoy @Alex Volovoy를 사용해야 .dismiss()와 함께ProgressDialog▁on▁it것▁to▁remove▁in우.실행하면 끝입니다.

progressDialog.hide(); // Don't use it, it gives error

progressDialog.dismiss(); // Use it

"Activity has leaked window that was originally added...다음 이후에 경고를 표시하려고 하면 오류가 발생합니다.Activity으로 입니다.finished.

AFAIK에는 두 가지 옵션이 있습니다.

  1. 을 다시 생각해 : call 알림다생시각: 통화dismiss()에서.dialog작업을 종료하기 전에 확인할 수 있습니다.
  2. 집어넣어요dialog합니다.thread)activity).

당신은 만들어야 합니다.Progressdialog가 는하반에 있습니다.onPreExecuteAsyncTask 러셔야하죠그하죠▁should.dismiss 있습니다.onPostExecute방법.

최상의 솔루션은 예외가 발생할 때 대화 상자 항목 추가 대화 상자 캡처 및 해제 대화 상자입니다.

아래 코드를 사용하십시오.

 try {
        dialog.show();
    } catch (Exception e) {
        dialog.dismiss();
    }

가장 좋은 해결책은 표시하기 전에 이 문제를 두는 것입니다.progressbar또는progressDialog

if (getApplicationContext().getWindow().getDecorView().isShown()) {

  //Show Your Progress Dialog

}

저의 경우 안드로이드 매니페스트 파일에 권한을 포함하는 것을 잊었기 때문입니다.

내가 어떻게 알아냈지요?@Bobby가 수락된 답변 아래에 있는 코멘트에서 말한 것처럼, 로그로 더 스크롤하기만 하면 예외를 실제로 던진 첫 번째 이유나 이벤트를 볼 수 있습니다.보기에 "Activity has leaked window what the firstally added"라는 메시지는 첫 번째 예외에서 발생한 예외일 뿐입니다.

아래 코드를 사용해 보십시오. 진행 대화를 해제할 때마다 작동하며 해당 인스턴스를 사용할 수 있는지 여부를 확인할 수 있습니다.

try {
        if (null != progressDialog && progressDialog.isShowing()) {
            progressDialog.dismiss();
            progressDialog = null;
        }
    } catch (Exception e) {
        e.printStackTrace();
    }

창 누출 예외에는 두 가지 이유가 있습니다.

활동 컨텍스트가 존재하지 않는 경우 대화 상자를 표시합니다. 이 문제를 해결하려면 활동이 존재하는지 확인하는 대화 상자만 표시해야 합니다.

if(getActivity()!= null && !getActivity().isFinishing()){
        Dialog.show();
}

대화 상자를 적절히 해제하지 마십시오. 해결하려면 다음 코드를 사용하십시오.

@Override
public void onDestroy(){
    super.onDestroy();
    if ( Dialog!=null && Dialog.isShowing() ){
        Dialog.dismiss();
}
}

백그라운드에서 토스트 스레드를 표시할 때 이 오류가 발생했습니다.UI 스레드에서 UI 관련 코드를 실행하여 해결되었습니다.

이에 대한 다른 해결책이 있는데, 이 방법이 유효한지 알고 싶습니다. 주요 해결책인 것처럼 보이는 onDestroy에서 제거하는 대신 ProgressDialog를 확장합니다.

public class MyProgressDialog extends ProgressDialog {

  private boolean isDismissed;

  public MyProgressDialog(Context context) {
    super(context);
  }

  @Override
  public void onDetachedFromWindow() {
    super.onDetachedFromWindow();
    dismiss();
  }

  @Override
  public void dismiss() {
    if (isDismissed) {
      return;
    }
    try {
      super.dismiss();
    } catch (IllegalArgumentException e) {
      // ignore
    }
    isDismissed = true;
  }

이것이 더 바람직합니다, 아프아이케이, 왜냐하면 당신은 멤버로서 진행 대화를 잡을 필요가 없기 때문입니다, 그냥 발사(쇼)하고 잊어버리세요.

언급URL : https://stackoverflow.com/questions/2850573/activity-has-leaked-window-that-was-originally-added

반응형