etc./StackOverFlow

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

청렴결백한 만능 재주꾼 2023. 4. 26. 12:46
반응형

질문자 :Pentium10


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

 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

이 오류는 상황에 따라 약간 오해의 소지가 있을 수 있습니다(답변은 여전히 완전히 정확하지만). 즉, 제 경우에는 처리되지 않은 예외가 AsyncTask에서 발생하여 활동이 종료된 다음 열린 진행 대화 상자가 이 예외를 일으켰습니다. '실제' 예외는 로그에서 조금 더 일찍 발생했습니다.

답변 3

onPause() 또는 onDestroy()와 같이 활동을 종료하기 전에 생성한 Dialog 인스턴스에서 해제()를 호출합니다.


Alex Volovoy

Activity 종료하기 전에 viewP.java:183 에서 생성한 Dialog dismiss() 를 호출하는 것입니다(예: onPause() . Activity 를 떠나기 전에 모든 Window s& Dialog 닫아야 합니다.


molnarm

AsyncTask 를 사용하는 경우 해당 로그 메시지가 기만적일 수 있습니다. AsyncTask doInBackground() 메서드에 있는 다른 오류를 찾을 수 있습니다. 이 오류는 현재 ActivityAsyncTask 가 다시 돌아오면 .. 글쎄요. 쉬다. 일부 다른 사용자는 이미 여기에서 설명했습니다 :-)


ggomeze

내가 실수로 호출하여이 오류를 트리거 hide() 대신 dismiss()AlertDialog .


Mark Phillip

예를 들어, Switch 문에서 break call 문을 놓친 경우 AlertDialog 를 표시한 후 finish() 호출하는 등 단순/멍청한 실수로 이 예외를 얻을 수 있습니다.

 @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 는 여전히 표시됩니다!

따라서 코드를 유심히 볼 때 잘못된 스레딩 문제 또는 복잡한 코딩 등을 찾을 때 나무가 있는 숲을 놓치지 마십시오. 때로는 누락된 break 문처럼 간단하고 멍청한 것일 수 있습니다. :)


Adrian Romanelli

이 질문에 대한 대답은 모두 정확했지만 실제로 그 이유를 이해하기에는 약간 혼란스러웠습니다. 약 2시간 동안 놀고 난 후 이 오류(내 경우)가 발생한 이유는 다음과 같습니다.

다른 답변을 읽고 이미 알고 있습니다. X has leaked window DecorView@d9e6131[] 오류는 앱이 닫힐 때 대화 상자가 열렸음을 의미합니다. 하지만 왜?

대화 상자가 열려 있는 동안 앱이 다른 이유로 충돌했을 수 있습니다.

이로 인해 코드의 일부 버그로 인해 앱이 닫히고, 다른 오류로 인해 앱이 닫힌 것과 동시에 대화 상자가 열려 있는 상태로 유지됩니다.

따라서 논리를 살펴보십시오. 첫 번째 오류를 해결하면 두 번째 오류가 저절로 해결됩니다. 여기에 이미지 설명 입력

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


Ruchir Baronia

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

방금 다음 코드를 작성하여 이 문제를 해결했습니다.

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

기본적으로 어떤 클래스에서 progressDialog를 시작했는지 onDestroy 메서드를 재정의하고 이 방식으로 수행합니다. "Activity has leaked window" 문제가 해결되었습니다.


Shoaib Ahmed

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

이 문제의 원인은 대화 상자가 닫히기 전에 활동이 닫히기 때문입니다. 위와 같은 현상이 발생하는 데에는 여러 가지 이유가 있습니다. 위의 글에서 언급한 내용도 맞습니다.

스레드에서 예외를 던지는 함수를 호출했기 때문에 상황이 발생했습니다. 그 때문에 창이 닫히고 예외가 발생했습니다.


Tushar

도움이 될 수 있습니다.

 if (! isFinishing()) { dialog.show(); }

sandy

활동이 파괴되면 대화 상자 닫기

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

Muhammad Aamir Ali

동일한 모호한 오류 메시지가 있었고 이유를 몰랐습니다. 이전 답변의 단서를 제공하여 mDialog.finish()에 대한 비 GUI 호출을 mDialog.dismiss()로 변경하고 오류가 사라졌습니다. 이것은 내 위젯의 동작에 영향을 미치지 않았지만 당혹스러웠고 중요한 메모리 누수에 플래그를 지정할 수 있었습니다.


Melinda Green

내 비디오 플레이어 응용 프로그램에서 이러한 로그를 얻었습니다. 이 메시지는 비디오 플레이어가 닫혀 있는 동안 발생했습니다. 흥미롭게도 나는 이러한 로그를 무작위로 몇 번 실행하곤 했습니다. 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(); }

mVideoView.pause() 를 호출하고 visibilityGONE 설정 OnPause 를 재정의합니다. 이 방법으로 " Activity has leaked window " 로그 오류 문제를 해결할 수 있습니다.


InvisiblePoint

나는 같은 문제를 겪고 있었고 이 페이지를 찾았고 내 상황은 다르지만 경고 상자를 정의하기 전에 if 블록에서 finish

따라서, 단순히 호출 dismiss (아직 제작되지 않았기 때문에) 작동하지 않을 것입니다하지만 알렉스 Volovoy의 답변을 읽고 실현 후 그것을 일으키는 경고 상자이었다. if 블록 내부의 완료 직후에 return 문을 추가하려고 시도했는데 문제가 해결되었습니다.

나는 당신이 마침을 부르면 모든 것을 멈추고 바로 끝낼 것이라고 생각했지만, 그렇지 않습니다. 코드 블록의 끝으로 이동한 다음 완료되는 것 같습니다.

따라서 일부 코드를 수행하기 전에 종료되는 상황을 구현하려면 완료 직후에 return 문을 넣어야 합니다. 그렇지 않으면 계속 진행되고 종료가 마지막에 호출된 것처럼 작동합니다. 호출한 코드 블록이 아닙니다. 그래서 이상한 오류가 모두 발생했습니다.

 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(); 따라서 대화 상자를 표시한 직후에 완료하여 창이 누출되었다고 말할 수 있습니다. 그렇지 않은 경우에도 여전히 그렇다고 생각합니다.

나는 이것이 내가 생각했던 것과 다르게 작동하는 종료 명령을 보여주기 때문에 여기에 추가할 것이라고 생각했고, 내가 이것을 발견하기 전에 나와 같은 생각을 하는 다른 사람들이 있을 것이라고 생각합니다.


Kit Ramos

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

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

 android:noHistory="true"

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


Killer

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

 // 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(); } }

Bapusaheb Shinde

AlertDialog 를 닫고 싶지만 활동 내 에서 참조를 유지하고 싶지 않을 때의 해결책이 있습니다.

솔루션에는 프로젝트에 androidx.lifecycle 종속성이 있어야 합니다(댓글 시점에서 일반적인 요구 사항이라고 생각합니다)

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

따라서 관찰자는 대화에 대한 참조를 유지하고 활동은 관찰자에 대한 참조를 유지합니다. "onPause"가 발생하면 관찰자가 대화 상자를 닫고 "onDestroy"가 발생하면 활동이 관찰자를 제거하므로 누출이 발생하지 않습니다(적어도 더 이상 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() }

dmz9

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

예시:

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

Kulbhushan Chaskar

ProgressDialog가 계속 표시될 때 활동을 완료하는 문제가 있었습니다.

따라서 먼저 대화 상자를 숨긴 다음 활동을 마칩니다.


LeonS

다음 코드를 시도해 보세요.

 public class Sample extends Activity(){ @Override public void onCreate(Bundle instance){ } @Override public void onStop() { super.onStop(); progressdialog.dismiss(); // try this } }

tinku

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();

NickUnuchek

AsyncTask 에서 ProgressDialog 를 사용할 때 발생했습니다. 실제로 나는 onPostExecute hide() 메서드를 사용하고 있습니다. @Alex Volovoy의 답변을 기반으로 onPostExecute에서 제거하고 완료하려면 ProgressDialog 와 함께 dismiss()

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

SANAT

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

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

  1. 경고 로그인을 다시 생각하십시오. 실제로 활동을 종료하기 전에 dialog 에서 dismiss()
  2. dialog 를 다른 스레드에 넣고 해당 thread 에서 실행합니다(현재 activity 과 무관).

Kyle Clegg

당신은 확인해야 Progressdialog 에서 객체 onPreExecute 방법 AsyncTask 당신은해야 dismiss 에 그것을 onPostExecute 방법.


ammad

가장 좋은 해결책은 예외가 발생할 때 try catch에 대화 상자를 추가하고 대화 상자를 닫는 것입니다.

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

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

Ness Tyagi

제 경우에는 Android 매니페스트 파일에 권한을 포함하는 것을 잊었기 때문입니다.

내가 어떻게 알아냈어? 글쎄요, @Bobby가 허용된 답변 아래의 주석에서 말한 것처럼 로그까지 더 스크롤하면 실제로 예외를 던진 첫 번째 이유나 이벤트가 표시됩니다. 분명히 "활동에 원래 추가된 창이 누수되었습니다"라는 메시지는 첫 번째 예외가 무엇이든 간에 발생한 예외일 뿐입니다.


MLQ

아래 코드를 시도하면 진행 대화 상자를 닫을 때마다 작동하며 해당 인스턴스가 사용 가능한지 여부를 확인할 수 있습니다.

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

Developer

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

1) 활동 컨텍스트가 존재하지 않을 때 대화 상자 표시, 이 문제를 해결하려면 활동이 존재한다고 확신하는 경우에만 대화 상자를 표시해야 합니다.

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

2) 이 코드를 사용하여 해결하려면 대화 상자를 적절하게 닫지 마십시오.

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

Sherry

progressbar 표시줄 또는 progressDialog 를 표시하기 전에 이것을 넣는 것입니다.

 if (getApplicationContext().getWindow().getDecorView().isShown()) { //Show Your Progress Dialog }

Ali Akram

이에 대한 또 다른 솔루션이 있으며 이것이 유효한지 알고 싶습니다. 선도적인 솔루션인 것처럼 보이는 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; }

AFAIC가 더 좋습니다. 진행 대화 상자를 구성원으로 보유할 필요가 없고 실행(표시)하고 잊어버리면 되기 때문입니다.


Kalisky

 if (mActivity != null && !mActivity.isFinishing() && mProgressDialog != null && mProgressDialog.isShowing()) { mProgressDialog.dismiss(); }

androidmalin

출처 : http:www.stackoverflow.com/questions/2850573/activity-has-leaked-window-that-was-originally-added

반응형