Ich verwende ACRA, um App-Abstürze zu melden. Ich erhielt eine View not attached to window manager
Fehlermeldung und dachte, ich hätte sie behoben, indem ich die pDialog.dismiss();
if-Anweisung umschloss:
if (pDialog!=null)
{
if (pDialog.isShowing())
{
pDialog.dismiss();
}
}
Es hat die Anzahl der View not attached to window manager
Abstürze reduziert, die ich erhalte, aber ich bekomme immer noch einige und bin mir nicht sicher, wie ich es lösen soll.
Fehlermeldung:
java.lang.IllegalArgumentException: View not attached to window manager
at android.view.WindowManagerGlobal.findViewLocked(WindowManagerGlobal.java:425)
at android.view.WindowManagerGlobal.removeView(WindowManagerGlobal.java:327)
at android.view.WindowManagerImpl.removeView(WindowManagerImpl.java:83)
at android.app.Dialog.dismissDialog(Dialog.java:330)
at android.app.Dialog.dismiss(Dialog.java:312)
at com.package.class$LoadAllProducts.onPostExecute(class.java:624)
at com.package.class$LoadAllProducts.onPostExecute(class.java:1)
at android.os.AsyncTask.finish(AsyncTask.java:631)
at android.os.AsyncTask.access$600(AsyncTask.java:177)
at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:644)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:176)
at android.app.ActivityThread.main(ActivityThread.java:5419)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:525)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1046)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:862)
at dalvik.system.NativeStart.main(Native Method)
Code-Auszug:
class LoadAllProducts extends AsyncTask<String, String, String>
{
/**
* Before starting background thread Show Progress Dialog
* */
@Override
protected void onPreExecute()
{
super.onPreExecute();
pDialog = new ProgressDialog(CLASS.this);
pDialog.setMessage("Loading. Please wait...");
pDialog.setIndeterminate(false);
pDialog.setCancelable(false);
pDialog.show();
}
/**
* getting All products from url
* */
protected String doInBackground(String... args)
{
// Building Parameters
doMoreStuff("internet");
return null;
}
/**
* After completing background task Dismiss the progress dialog
* **/
protected void onPostExecute(String file_url)
{
// dismiss the dialog after getting all products
if (pDialog!=null)
{
if (pDialog.isShowing())
{
pDialog.dismiss(); //This is line 624!
}
}
something(note);
}
}
Manifest:
<activity
android:name="pagename.CLASS"
android:configChanges="keyboard|keyboardHidden|orientation|screenSize|screenLayout"
android:label="@string/name" >
</activity>
Was fehlt mir, um diesen Absturz zu verhindern?
AsyncTask
ist drinnen deklariertActivity
oderFragment
?Antworten:
So reproduzieren Sie den Fehler:
Settings -> Developer Options -> Don't keep Activities
.AsyncTask
ausgeführt wird und dasProgressDialog
angezeigt wird.Das Android-Betriebssystem zerstört eine Aktivität, sobald sie ausgeblendet ist. Wenn
onPostExecute
aufgerufenActivity
wird, befindet sich der Wille im Zustand "Fertig stellen" und derProgressDialog
Wille wird nicht angehängtActivity
.Wie man es repariert:
onPostExecute
Methode.ProgressDialog
in-onDestroy
Methode. Andernfalls wird eineandroid.view.WindowLeaked
Ausnahme ausgelöst. Diese Ausnahme tritt normalerweise in Dialogen auf, die nach Abschluss der Aktivität noch aktiv sind.Versuchen Sie diesen festen Code:
quelle
isDestroyed()
mehr alsisFinishing()
für diesen Zweck auf alle APIs?isFinishing()
nicht garantiert werden,true
dass die Aktivität vom System zerstört wird. Weitere Informationen finden Sie in der Dokumentation zu Aktivitäten .// or call isFinishing() if min sdk version < 17
er auf dieselbe Ausnahme. Wir brauchen also eine andere Lösung als diese Antwort für Apps, die auf API <17 ausgeführt werden.myActivityWeakReference.get() != null && !myActivityWeakReference.get().isFinishing()
Problem könnte sein, dass die gewesen
Activity
sindfinished
oder inprogress of finishing
.Fügen Sie einen Scheck hinzu
isFinishing
und schließen Sie den Dialog nur dann, wenn dies der Fall istfalse
isFinishing: Überprüfen Sie, ob diese Aktivität gerade beendet wird, entweder weil Sie sie aufgerufen
finish
haben oder weil jemand anderes sie beendet hat.quelle
Für die
Dialog
Erstellung in a verwendeFragment
ich den folgenden Code:Ich benutze dieses Muster, um den Fall zu behandeln, in dem a
Fragment
von der gelöst werden kannActivity
.quelle
Sehen Sie hier, wie der Code funktioniert:
Nach dem Aufrufen der Async-Task wird die Async-Task im Hintergrund ausgeführt. das ist wünschenswert. Diese Async-Aufgabe verfügt nun über einen Fortschrittsdialog, der an die Aktivität angehängt ist, wenn Sie fragen, wie der Code angezeigt werden soll:
Sie übergeben den
Class.this
as-Kontext an das Argument. Der Fortschrittsdialog ist also weiterhin an die Aktivität angehängt.Stellen Sie sich nun das Szenario vor: Wenn wir versuchen, die Aktivität mit der Methode finish () zu beenden, während die asynchrone Aufgabe ausgeführt wird, ist dies der Punkt, an dem Sie versuchen, auf die an die Aktivität angehängte Ressource zuzugreifen, dh
progress bar
wenn die Aktivität nicht mehr ausgeführt wird Dort.Daher erhalten Sie:
Lösung dafür:
1) Stellen Sie sicher, dass das Dialogfeld geschlossen oder abgebrochen wird, bevor die Aktivität beendet wird.
2) Beenden Sie die Aktivität erst, nachdem das Dialogfeld geschlossen wurde, dh die asynchrone Aufgabe ist beendet.
quelle
Activity
. Android kann es jederzeit beenden. # 2 macht also keinen Sinn.Basierend auf der Antwort von @erakitin, aber auch kompatibel für Android-Versionen <API-Stufe 17. Leider wird Activity.isDestroyed () erst seit API-Stufe 17 unterstützt. Wenn Sie also genau wie ich auf eine ältere API-Stufe abzielen, müssen Sie dies tun überprüfe es selbst. Habe danach keine
View not attached to window manager
Ausnahme mehr.Beispielcode
quelle
verweisen Sie dies .
quelle
OnConfigurationChanged überschreiben und Fortschrittsdialog schließen. Wenn der Fortschrittsdialog im Hochformat erstellt und im Querformat geschlossen wird, wird die Ansicht nicht an den Fenstermanagerfehler angehängt.
Stoppen Sie auch den Fortschrittsbalken und die asynchrone Aufgabe in den Methoden onPause (), onBackPressed und onDestroy.
quelle
Überschreiben Sie die Zerstörung der Aktivität und schließen Sie Ihren Dialog ab und machen Sie ihn null
quelle
Erstens ist der Absturzgrund, dass der Index von decorView -1 ist. Wir können ihn aus dem Android-Quellcode erkennen. Es gibt ein Code-Snippet:
Damit wir die folgende Auflösung erhalten, beurteilen Sie einfach den Index von decorView. Wenn er mehr als 0 beträgt, fahren Sie fort oder kehren Sie einfach zurück und geben Sie die Entlassung auf. Code wie folgt:
quelle
Überschreiben Sie die
dismiss()
Methode wie folgt :Um das Problem zu reproduzieren, beenden Sie einfach die Aktivität, bevor Sie den Dialog schließen.
quelle
beste Lösung. Überprüfen Sie, ob der erste Kontext der Aktivitätskontext oder der Anwendungskontext ist. Wenn der Aktivitätskontext nur die Aktivität beendet ist oder nicht, rufen Sie
dialog.show()
oder aufdialog.dismiss();
Wenn Sie weitere Prüfungen hinzufügen möchten, fügen Sie eine Bedingung hinzu
dialog.isShowing()
oderdialog !-null
verwenden Sie sie&&
.quelle
Dieses Problem ist darauf zurückzuführen, dass Ihre Aktivität beendet ist, bevor die Entlassungsfunktion aufgerufen wird. Behandeln Sie die Ausnahme und überprüfen Sie Ihr ADB-Protokoll auf den genauen Grund.
quelle
Ich habe eine Möglichkeit, diese Ausnahme zu reproduzieren.
Ich benutze 2
AsyncTask
. Einer erledigt eine lange Aufgabe und ein anderer eine kurze Aufgabe. Rufen Sie nach Abschluss der kurzen Aufgabe anfinish()
. Wenn eine lange Aufgabe abgeschlossen und aufgerufen wurdeDialog.dismiss()
, stürzt sie ab.Hier ist mein Beispielcode:
Sie können dies versuchen und herausfinden, wie Sie dieses Problem am besten beheben können. Aus meiner Studie geht hervor, dass es mindestens vier Möglichkeiten gibt, dies zu beheben:
isFinishing()
, um den Status der Aktivität zu überprüfenAsyncTask.cancel(false)
anonDestroy()
. Dadurch wird verhindert, dass die Asynctask ausgeführt wird,onPostExecute()
aberonCancelled()
stattdessen ausgeführt.Hinweis:
onPostExecute()
Wird auch dann ausgeführt, wenn SieAsyncTask.cancel(false)
ein älteres Android-Betriebssystem wie Android 2.XX aufrufenSie können das beste für Sie auswählen.
quelle
Möglicherweise initialisieren Sie pDialog global, entfernen es dann und initialisieren Ihre Ansicht oder Ihren Dialog lokal. Ich habe das gleiche Problem, ich habe dies getan und mein Problem ist behoben. Hoffe es wird für dich funktionieren.
quelle
Wir haben auch unseren Dialog über
onPause
Methode oderonDestroy
Methode abgelehntquelle