Die Aktivität hat ein Fenster verloren, das ursprünglich hinzugefügt wurde

Was ist dieser Fehler und warum passiert das?

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

Sie versuchen, ein Dialogfeld anzuzeigen, nachdem Sie eine Aktivität beendet haben.

[BEARBEITEN]

Diese Frage ist eine der Top-Suche auf Google für Android-Entwickler, daher einige wichtige Punkte aus Kommentaren hinzufügen, die für zukünftige Ermittler hilfreicher sein könnte, ohne eingehende Kommentar-Konversation zu gehen.

Antwort 1 :

Sie versuchen, ein Dialogfeld anzuzeigen, nachdem Sie eine Aktivität beendet haben.

Antwort 2

Dieser Fehler kann unter Umständen etwas irreführend sein (obwohl die Antwort immer noch vollständig korrekt ist) – dh in meinem Fall wurde eine nicht behandelte Exception in eine AsyncTask geworfen, die zum Herunterfahren der Activity führte, dann verursachte ein geöffneter Progressdialog diese Exception die “echte” Ausnahme war etwas früher im Protokoll

Antwort 3

Rufen Sie kill () in der Dialog-Instanz auf, die Sie vor dem Beenden Ihrer Aktivität erstellt haben, zB in onPause () oder onDestroy ()

Die Lösung besteht darin dismiss() in dem Dialog Sie in viewP.java:183 erstellt viewP.java:183 vor dem Beenden der Activity (z. B. in onPause() . Alle Window und Dialog sollten vor dem Verlassen einer Activity .

Wenn Sie AsyncTask , kann diese Protokollnachricht möglicherweise trügerisch sein. Wenn Sie in Ihrem Protokoll nachschlagen, finden Sie möglicherweise einen weiteren Fehler, wahrscheinlich einen in Ihrer doInBackground() Methode Ihrer AsyncTask , der Ihre aktuelle Activity in die Luft AsyncTask und somit, sobald die AsyncTask zurückkommt. AsyncTask , Sie kennen die rest. Einige andere Benutzer haben das bereits hier erklärt 🙂

Sie können diese Ausnahme nur durch einen einfachen / dummen Fehler erhalten, indem Sie zum Beispiel nach dem Anzeigen eines AlertDialog versehentlich finish() AlertDialog , wenn Sie in einer Switch-statement eine Break-Call-statement verpassen …

  @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; } } 

Die Methode finish() die Activity , aber der AlertDialog wird weiterhin AlertDialog !

Wenn Sie sich also den Code genau ansehen und nach Problemen mit dem Threading oder nach komplexen Codierungen suchen, sollten Sie den Wald für die Bäume nicht aus den Augen verlieren. Manchmal kann es einfach so einfach und dumm sein wie eine fehlende Break-statement. 🙂

Ich habe diesen Fehler ausgetriggers, indem ich bei einem AlertDialog fälschlicherweise hide() anstelle von AlertDialog dismiss() AlertDialog .

Dieses Problem tritt auf, wenn Sie versuchen, nach dem Beenden einer Aktivität ein Dialogfeld anzuzeigen.

Ich habe dieses Problem nur getriggers, indem ich den folgenden Code aufschrieb:

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

Im Grunde genommen, von welcher class Sie progressDialog gestartet haben, überschreiben Sie die Methode onDestroy und tun dies. Es triggerse “Aktivität hat durchsickerndes Fenster” Problem.

Ich bin kürzlich auf dasselbe Problem gestoßen.

Der Grund für dieses Problem ist, dass die Aktivität geschlossen wird, bevor der Dialog geschlossen wird. Es gibt verschiedene Gründe dafür. Die in den obigen Posts erwähnten sind ebenfalls korrekt.

Ich bin in eine Situation geraten, weil im Thread ich eine function genannt habe, die Ausnahme warf. Aufgrund dessen wurde das Fenster geschlossen und damit die Ausnahme.

Die Antworten auf diese Frage waren alle richtig, aber ein wenig verwirrend für mich, warum ich wirklich verstehe. Nachdem ich ungefähr 2 Stunden herumgespielt hatte, traf mich der Grund für diesen Fehler (in meinem Fall):

Sie wissen bereits, aus dem Lesen anderer Antworten, dass das hat X has leaked window DecorView@d9e6131[] Fehler bedeutet, dass ein Dialogfeld geöffnet war, als Ihre App geschlossen wurde. Aber warum?

Es könnte sein, dass Ihre App aus einem anderen Grund abgestürzt ist, während Ihr Dialog geöffnet war

Dies führte dazu, dass Ihre App wegen eines Fehlers in Ihrem Code geschlossen wurde, was dazu führte, dass der Dialog gleichzeitig mit dem Schließen der App aufgrund des anderen Fehlers geöffnet blieb.

Also, schau durch dein Logisches. Löse den ersten Fehler und dann triggers sich der zweite Fehler auf Bildbeschreibung hier eingeben

Ein Fehler verursacht einen anderen, der einen anderen verursacht, wie DOMINOS!

Ich hatte die gleiche obskure Fehlermeldung und hatte keine Ahnung warum. Aufgrund von Hinweisen aus den vorherigen Antworten habe ich meine nicht-GUI-Aufrufe zu mDialog.finish () geändert, um mDialog.dismiss () zu sein, und die Fehler verschwanden. Dies hatte keinen Einfluss auf das Verhalten meines Widgets, aber es war beunruhigend und hätte möglicherweise ein wichtiges Speicherleck anzeigen können.

Ich habe diese Logs in meiner Videoplayer-Anwendung erhalten. Diese Nachrichten wurden ausgetriggers, während der Videoplayer geschlossen wurde. Interessanterweise habe ich diese Logs einmal zufällig in ein paar Läufen erhalten. Auch meine Bewerbung beinhaltet keinen progressdialog . Schließlich habe ich dieses Problem mit der folgenden Implementierung getriggers.

 @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 den OnPause mit Aufruf von mVideoView.pause() und setzen Sie die visibility auf GONE . Auf diese Weise konnte ich das Log-Fehlerproblem ” Activity has leaked window ” beheben.

Schließen Sie den Dialog, wenn die Aktivität zerstört wird

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

Ich hatte das gleiche Problem und fand diese Seite, und während meine Situation anders war, rief ich finish von einem if Block an, bevor es die Alarmbox definierte.

Also, einfach die dismiss anzurufen würde nicht funktionieren (wie es noch nicht gemacht wurde), aber nachdem ich Alex Volovoys Antwort gelesen hatte und mir klar wurde, dass es die Alarmbox war, die das verursachte. Ich habe versucht, eine Return-statement direkt nach dem Finish innerhalb der if Block hinzufügen und das Problem behoben.

Ich dachte, wenn du einmal angerufen hast, hat es alles aufgehört und genau dort beendet, aber das tut es nicht. Es scheint bis zum Ende des Codeblocks zu gehen, in dem es dann endet.

Also, wenn du eine Situation implementieren willst, in der es manchmal endet, bevor du etwas Code machst, dann musst du direkt nach dem Ziel eine Return – Aussage machen, oder es wird weitergehen und so tun, als ob das Ziel am Ende des Block des Codes nicht wo Sie es genannt haben. Deshalb habe ich all diese seltsamen Fehler bekommen.

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

Wenn du die Rückgabe nicht richtig machst, nachdem ich angerufen habe, wird es so tun, als ob du es nach der alert.show(); aufgerufen alert.show(); und deshalb würde es sagen, dass das Fenster durchsickert ist, indem es fertig ist, nachdem Sie den Dialog erscheinen ließen, obwohl das nicht der Fall ist, denkt es immer noch.

Ich dachte, ich würde das hier hinzufügen, da dies zeigt, dass der Finish-Befehl anders wirkte, als ich dachte, und ich denke, es gibt andere Leute, die genauso denken wie ich, bevor ich das entdeckte.

Dies könnte helfen.

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

Dies ist nicht die Antwort auf die Frage, aber es ist relevant für das Thema.

Wenn die Aktivität ein Attribut im Manifest definiert hat

  android:noHistory="true" 

Nach dem Ausführen von onPause () geht der Kontext der Aktivität verloren. Daher können alle Ansichten, die diesen Kontext verwenden, diesen Fehler verursachen.

Versuchen Sie nicht nur, eine Warnung anzuzeigen, sondern sie kann auch aufgerufen werden, wenn Sie eine bestimmte Instanz einer Aktivität beenden und versuchen, eine neue Aktivität / einen neuen Dienst zu starten oder sie zu stoppen.

Beispiel:

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

Dies kann der Fall sein, wenn Sie bei der function doInBackground() einen Fehler haben und diesen Code haben.

Versuchen Sie, den Dialog zuletzt hinzuzufügen. Zuerst überprüfe und doInBackground() die doInBackground() function

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

Das ist mir passiert, wenn ich ProgressDialog in AsyncTask . Eigentlich verwende ich die Methode hide() in onPostExecute . Basierend auf der Antwort von @Alex Volovoy muss ich ablehnen dismiss() mit ProgressDialog , um es in onPostExecute entfernen und es ist fertig.

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

Der Fehler ” Activity has leaked window that was originally added... ” tritt auf, wenn Sie versuchen, eine Warnung anzuzeigen, nachdem die Activity effektiv finished .

Sie haben zwei Möglichkeiten AFAIK:

  1. Erinnern Sie sich an die Anmeldung Ihrer Warnung: Rufen Sie im dialog die dialog dismiss() bevor Sie Ihre Aktivität beenden.
  2. Fügen Sie den dialog in einen anderen Thread ein und führen Sie ihn in diesem thread (unabhängig von der aktuellen activity ).

Hatte das Problem, wo ich eine Aktivität beendet habe, als ein ProgressDialog noch angezeigt wurde.

Verstecken Sie also zuerst den Dialog und beenden Sie dann die Aktivität.

Probieren Sie diesen Code aus:

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

Sie müssen Progressdialog Objekt in onPreExecute Methode von AsyncTask und Sie sollten es auf onPostExecute Methode onPostExecute .

Die beste Lösung besteht darin, den Dialog try catch and discuss einfach hinzuzufügen, wenn eine Ausnahme auftritt

Verwenden Sie einfach den folgenden Code

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

Im Allgemeinen tritt dieses Problem aufgrund des Fortschrittsdialogs auf: Sie können dies mithilfe einer der folgenden Methoden in Ihrer Aktivität beheben:

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

In meinem Fall lag der Grund darin, dass ich vergessen habe, eine Berechtigung in die Android-Manifestdatei aufzunehmen.

Wie habe ich es herausgefunden? Nun, genau wie @Bobby in einem Kommentar unter der angenommenen Antwort sagt, scrollen Sie einfach weiter zu Ihren Logs und Sie werden den ersten Grund oder das erste Ereignis sehen, das die Exception ausgetriggers hat. Offenbar ist die Meldung “Aktivität hat Fenster, das ursprünglich geleakt wurde”, nur eine Ausnahme, die sich aus der ersten Ausnahme ergibt.

Probieren Sie den folgenden Code aus: Er wird immer funktionieren, wenn Sie den Fortschrittsdialog ablehnen und er sieht, ob seine Instanz verfügbar ist oder nicht.

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

Stellen Sie nur sicher, dass Ihre Aktivität aufgrund einiger Ausnahmen, die irgendwo in Ihrem Code ausgetriggers werden, nicht unerwartet geschlossen wird. Im Allgemeinen geschieht dies in einer asynchronen Aufgabe, wenn die Aktivität in der doinBackground-Methode zwangsweise geschlossen wird und asynctask dann zur onPosterexecute-Methode zurückkehrt.

Ausgetriggerse Fensterausfälle haben zwei Gründe:

1) Zeigen Sie den Dialog, wenn der Aktivitätskontext nicht existiert. Um dies zu lösen, sollten Sie den Dialog nur dann anzeigen, wenn Sie sicher sind, dass Aktivität vorhanden ist:

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

2) nicht den Dialog entsprechend ablehnen, um diesen Code zu lösen:

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

Das Problem nach mir ist, dass Sie versuchen, einen Dialog direkt nach Abschluss einer Aktivität aufzurufen, also was Sie tun können, ist eine Verzögerung mit Handler und Ihr Problem wird getriggers für zB:

  Handler handler=new Handler(); handler.postDelayed(new Runnable() { @Override public void run() { dialog.show(); //or dialog.dismiss(); } },100); 

Ich habe das gleiche Problem. Der Fehler war nicht im Dialog sondern in einem EditText . Ich habe versucht, den Wert des Edittext innerhalb einer Assynctask . Der einzige Weg, den ich lösen konnte, war das Erstellen eines neuen runnable .

 runOnUiThread(new Runnable(){ @Override public void run() { ... } });