Was ist dieser Fehler und warum passiert er?
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)
android
memory-leaks
dialog
Pentium10
quelle
quelle
Antworten:
Sie versuchen, einen Dialog anzuzeigen, nachdem Sie eine Aktivität beendet haben.
[BEARBEITEN]
Diese Frage ist eine der häufigsten Suchanfragen bei Google für Android-Entwickler. Daher werden einige wichtige Punkte aus Kommentaren hinzugefügt, die für zukünftige Ermittler hilfreich sein könnten, ohne sich eingehend mit Kommentaren zu befassen.
Antwort 1 :
Antwort 2
Antwort 3
quelle
Die Lösung besteht darin,
dismiss()
das vonDialog
Ihnen erstellte aufzurufen,viewP.java:183
bevor Sie das verlassenActivity
, zonPause()
. AlleWindow
s &Dialog
s sollten vor dem Verlassen eines geschlossen werdenActivity
.quelle
Wenn Sie verwenden
AsyncTask
, kann diese Protokollnachricht wahrscheinlich irreführend sein. Wenn Sie in Ihrem Protokoll nachschlagen, finden Sie möglicherweise einen weiteren Fehler, wahrscheinlich einen in IhrerdoInBackground()
Methode, der dazu führtAsyncTask
, dass Ihr StromActivity
explodiert, und wenn derAsyncTask
zurückkommt, kennen Sie den Rest. Einige andere Benutzer haben das hier bereits erklärt :-)quelle
doInBackground
derAsyncTask
Klasse verwendet habe, ohne sie jedoch in derAndroidManifest
Datei mit der folgenden Eigenschaft zu deklarierenandroid:name
:android:name="my.package.MyApplicationClass"
. Wenn Sie es verwenden, solltenAsyncTask
Sie immer daran denken, Ihre Warnung innerhalb der Methode zu instanziierenonPreExecute
und sie zu schließenonPostExecute
.Ich habe diesen Fehler ausgelöst, indem ich versehentlich
hide()
stattdismiss()
auf einen aufgerufen habeAlertDialog
.quelle
Sie können diese Ausnahme nur durch einen einfachen / dummen Fehler erhalten, indem Sie (zum Beispiel) versehentlich anrufen,
finish()
nachdem Sie eine angezeigt habenAlertDialog
, wenn Sie eine break call-Anweisung in einer switch-Anweisung verpassen ...Die
finish()
Methode schließt dasActivity
, aber dasAlertDialog
wird immer noch angezeigt!Wenn Sie also aufmerksam auf den Code starren, nach schlechten Threading-Problemen oder komplexer Codierung suchen, verlieren Sie den Wald vor lauter Bäumen nicht aus den Augen. Manchmal kann es einfach und dumm sein wie eine fehlende break-Anweisung. :) :)
quelle
Die Antworten auf diese Frage waren alle richtig, aber ein wenig verwirrend für mich, um tatsächlich zu verstehen, warum. Nachdem ich ungefähr 2 Stunden herumgespielt hatte, traf mich der Grund für diesen Fehler (in meinem Fall):
Durch das Lesen anderer Antworten wissen Sie bereits, dass der
X has leaked window DecorView@d9e6131[]
Fehler bedeutet , dass beim Schließen Ihrer App ein Dialogfeld geöffnet war. Aber warum?Es kann 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 aufgrund eines Fehlers in Ihrem Code geschlossen wurde, was dazu führte, dass der Dialog gleichzeitig mit dem Schließen Ihrer App aufgrund des anderen Fehlers geöffnet blieb.
Schauen Sie sich also Ihre Logik an. Lösen Sie den ersten Fehler, und der zweite Fehler löst sich von selbst
Ein Fehler verursacht einen anderen, der einen anderen verursacht, wie DOMINOS!
quelle
Dieses Problem tritt auf, wenn Sie versuchen, einen Dialog anzuzeigen, nachdem Sie eine Aktivität beendet haben.
Ich habe dieses Problem nur gelöst, indem ich den folgenden Code aufgeschrieben habe:
Grundsätzlich sollten Sie in welcher Klasse Sie progressDialog gestartet haben, die onDestroy-Methode überschreiben und auf diese Weise vorgehen. Es wurde das Problem "Aktivität hat Fenster durchgesickert" gelöst.
quelle
Ich hatte vor kurzem das gleiche Problem.
Der Grund für dieses Problem ist, dass die Aktivität geschlossen wird, bevor der Dialog beendet wird. Es gibt verschiedene Gründe dafür. Die in den obigen Beiträgen genannten sind ebenfalls korrekt.
Ich bin in eine Situation geraten, weil ich im Thread eine Funktion aufgerufen habe, die eine Ausnahme auslöste. Aufgrund dessen wurde das Fenster geschlossen und damit die Ausnahme.
quelle
Schließen Sie den Dialog, wenn die Aktivität zerstört wird
quelle
Das könnte helfen.
quelle
Ich hatte die gleiche obskure Fehlermeldung und hatte keine Ahnung warum. Angesichts der Hinweise aus den vorherigen Antworten habe ich meine Nicht-GUI-Aufrufe in mDialog.finish () in mDialog.dismiss () geändert, und die Fehler sind verschwunden. Dies hatte keinen Einfluss auf das Verhalten meines Widgets, war jedoch beunruhigend und hätte einen wichtigen Speicherverlust anzeigen können.
quelle
Ich habe diese Protokolle in meiner Video-Player-Anwendung erhalten. Diese Nachrichten wurden ausgelöst, während der Videoplayer geschlossen war. Interessanterweise habe ich diese Protokolle einmal in einigen Läufen auf zufällige Weise abgerufen. Auch meine Bewerbung beinhaltet keine
progressdialog
. Schließlich habe ich dieses Problem mit der folgenden Implementierung umgangen.Überschreiben Sie das
OnPause
with call tomVideoView.pause()
und das setvisibility
toGONE
. Auf diese Weise konnte ich das "Activity has leaked window
" Protokollfehlerproblem beheben .quelle
Ich hatte das gleiche Problem und fand diese Seite. Während meine Situation anders war, rief ich
finish
von einemif
Block aus an, bevor er die Warnbox definierte.Einfach anzurufen
dismiss
würde also nicht funktionieren (da es noch nicht gemacht wurde), aber nachdem ich Alex Volovoys Antwort gelesen und erkannt hatte, dass es die Alarmbox war , die es verursachte. Ich habe versucht, direkt nach dem Ende in diesemif
Block eine return-Anweisung hinzuzufügen , wodurch das Problem behoben wurde.Ich dachte, als du fertig angerufen hast, hat es alles gestoppt und ist genau dort fertig geworden, aber das tut es nicht. Es scheint bis zum Ende des Codeblocks zu gehen, in dem es sich befindet, und endet dann.
Wenn Sie also eine Situation implementieren möchten, in der es manchmal vor dem Ausführen von Code beendet wird, müssen Sie direkt nach dem Ende eine return-Anweisung einfügen, oder es geht weiter und verhält sich so, als ob das Ende am Ende des Codes aufgerufen wurde Codeblock nicht dort, wo Sie ihn genannt haben. Deshalb habe ich all diese seltsamen Fehler bekommen.
Wenn Sie die Rückgabe nicht direkt nach dem Aufruf von finish dort einfügen, verhält es sich so, als hätten Sie sie nach dem aufgerufen,
alert.show();
und daher würde das Fenster durch Beenden durchgesickert, sobald Sie den Dialog angezeigt haben, obwohl dies der Fall ist nicht der Fall, denke es immer noch.Ich dachte, ich würde dies wie hier hinzufügen, da dies zeigt, dass der Zielbefehl anders funktioniert als ich dachte, und ich würde vermuten, dass es andere Leute gibt, die genauso denken wie ich, bevor ich dies entdeckte.
quelle
Dies ist nicht die Antwort auf die Frage, aber sie ist für das Thema relevant.
Wenn die Aktivität ein Attribut im Manifest definiert hat
Nach der Ausführung von onPause () geht der Aktivitätskontext verloren. Alle Ansichten, die diesen Kontext verwenden, geben möglicherweise diesen Fehler aus.
quelle
progessdialog.show()
.. undprogressdialog.hide()
inasynctask
der gleichen Aktivität anstelle vononPause()
ab erzählenactivity
? Schauen Sie sich mein Problem an ... stackoverflow.com/questions/39332880/…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 zu stoppen.
Beispiel:
quelle
Im Allgemeinen tritt dieses Problem aufgrund des Fortschrittsdialogs auf: Sie können dieses Problem mithilfe einer der folgenden Methoden in Ihrer Aktivität lösen:
quelle
Hatte das Problem, wo ich eine Aktivität beendet habe, als noch ein ProgressDialog angezeigt wurde.
Blenden Sie also zuerst den Dialog aus und beenden Sie dann die Aktivität.
quelle
Versuchen Sie diesen Code:
quelle
progressdialog.dismiss();
Dadurch kann eine NullPointerException erstellt werden.Dies kann der Fall sein, wenn Sie einen
doInBackground()
Funktionsfehler haben und diesen Code haben.Versuchen Sie endlich, einen Dialog hinzuzufügen. Überprüfen und beheben Sie zunächst die
doInBackground()
Funktionquelle
Dies geschah zu mir , wenn ich verwende
ProgressDialog
inAsyncTask
. Eigentlich benutze ichhide()
Methode inonPostExecute
. Auf der Grundlage der Antwort von @ Alex Volovoy Ich brauche die Verwendungdismiss()
mitProgressDialog
ihm in OnPostExecute und ihre getan zu entfernen.quelle
AsyncTask
und das zeigenDialog
, passiert etwas, das denActivity
AufrufonPause()
ausführt (möglicherweise eine Logik in Ihrer AsyncTask selbst, wie ein Listener, dann wird es auslaufen. 2) Wie oben erwähnt, ist das,Dialog
was damit erstellt wurde,Activity
Context
niemals entlassen undActivity
geht weiter.Der
Activity has leaked window that was originally added...
Fehler " " tritt auf, wenn Sie versuchen, eine Warnung anzuzeigen, nachdem dieActivity
effektiv istfinished
.Sie haben zwei Möglichkeiten AFAIK:
dismiss()
die andialog
bevor Sie Ihre Aktivität tatsächlich beenden.dialog
in einen anderen Thread und führen Sie es darauf austhread
(unabhängig vom aktuellenactivity
).quelle
Hier ist eine Lösung, wenn Sie AlertDialog schließen möchten, aber keinen Verweis darauf in der Aktivität behalten möchten .
Lösung erfordert, dass Sie androidx.lifecycle haben Abhängigkeit in Ihrem Projekt haben (ich glaube, im Moment des Kommentars ist es eine häufige Anforderung)
Auf diese Weise können Sie die Entlassung von Dialogen an ein externes Objekt (Beobachter) delegieren, und Sie müssen sich nicht mehr darum kümmern, da sie sich automatisch abmeldet, wenn die Aktivität endet. (Hier ist der Beweis: https://github.com/googlecodelabs/android-lifecycles/issues/5 ).
Der Beobachter behält also den Bezug zum Dialog und die Aktivität den Bezug zum Beobachter. Wenn "onPause" passiert - der Beobachter schließt den Dialog und wenn "onDestroy" passiert - entfernt die Aktivität den Beobachter, so dass kein Leck auftritt (zumindest sehe ich keinen Fehler mehr in logcat).
quelle
Fenster durchgesickerte Ausnahmen haben zwei Gründe:
1) Anzeigen des Dialogfelds, wenn kein Aktivitätskontext vorhanden ist. Um dies zu lösen, sollten Sie das Dialogfeld nur anzeigen, wenn Sie sicher sind, dass Aktivität vorhanden ist:
2) Schließen Sie den Dialog nicht angemessen, um diesen Code zu lösen:
quelle
Sie müssen
Progressdialog
Objekt inonPreExecute
Methode von machenAsyncTask
und Sie solltendismiss
es aufonPostExecute
Methode.quelle
Die beste Lösung besteht darin, im Dialogfeld "Versuch abzufangen und zu schließen" einen Dialog hinzuzufügen, wenn eine Ausnahme auftritt
quelle
dialog.dismiss()
wird auch Fehler verursachenIn meinem Fall war der Grund, 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 akzeptierten Antwort sagt, scrollen Sie einfach weiter nach oben zu Ihren Protokollen und Sie werden den ersten Grund oder das erste Ereignis sehen, das die Ausnahme wirklich ausgelöst hat. Anscheinend ist die Meldung "Aktivität hat Fenster durchgesickert, das ursprünglich hinzugefügt wurde" nur eine Ausnahme, die sich aus der ersten Ausnahme ergibt.
quelle
Versuchen Sie es mit dem folgenden Code. Es funktioniert jedes Mal, wenn Sie den Fortschrittsdialog schließen und sehen, ob seine Instanz verfügbar ist oder nicht.
quelle
Die beste Lösung ist dies vor dem Anzeigen von
progressbar
oderprogressDialog
quelle
Stellen Sie einfach sicher, dass Ihre Aktivität nicht unerwartet aufgrund einiger Ausnahmen in Ihrem Code geschlossen wird. Im Allgemeinen tritt dies bei asynchronen Aufgaben auf, wenn die Aktivität in der doinBackground-Methode erzwungen wird und die asynctask dann zur onPostexecute-Methode zurückkehrt.
quelle
Ich habe eine andere Lösung dafür und würde gerne wissen, ob sie Ihnen gültig erscheint: Anstatt in onDestroy, das die führende Lösung zu sein scheint, zu verwerfen, erweitere ich ProgressDialog ...
Dies ist vorzuziehen, AFAIC, da Sie den Fortschrittsdialog nicht als Mitglied halten müssen, sondern nur feuern (anzeigen) und vergessen müssen
quelle