Ich habe eine Aktivität, die AsyncTask startet und den Fortschrittsdialog für die Dauer des Vorgangs anzeigt. Die Aktivität wird als NICHT durch Drehen oder Schieben der Tastatur neu erstellt deklariert.
<activity android:name=".MyActivity"
android:label="@string/app_name"
android:configChanges="keyboardHidden|orientation"
>
<intent-filter>
</intent-filter>
</activity>
Sobald die Aufgabe abgeschlossen ist, entlasse ich den Dialog, aber auf einigen Telefonen (Framework: 1.5, 1.6) wird ein solcher Fehler ausgegeben:
java.lang.IllegalArgumentException: View not attached to window manager
at android.view.WindowManagerImpl.findViewLocked(WindowManagerImpl.java:356)
at android.view.WindowManagerImpl.removeView(WindowManagerImpl.java:201)
at android.view.Window$LocalWindowManager.removeView(Window.java:400)
at android.app.Dialog.dismissDialog(Dialog.java:268)
at android.app.Dialog.access$000(Dialog.java:69)
at android.app.Dialog$1.run(Dialog.java:103)
at android.app.Dialog.dismiss(Dialog.java:252)
at xxx.onPostExecute(xxx$1.java:xxx)
Mein Code lautet:
final Dialog dialog = new AlertDialog.Builder(context)
.setTitle("Processing...")
.setCancelable(true)
.create();
final AsyncTask<MyParams, Object, MyResult> task = new AsyncTask<MyParams, Object, MyResult>() {
@Override
protected MyResult doInBackground(MyParams... params) {
// Long operation goes here
}
@Override
protected void onPostExecute(MyResult result) {
dialog.dismiss();
onCompletion(result);
}
};
task.execute(...);
dialog.setOnCancelListener(new OnCancelListener() {
@Override
public void onCancel(DialogInterface arg0) {
task.cancel(false);
}
});
dialog.show();
Nach dem, was ich gelesen ( http://bend-ing.blogspot.com/2008/11/properly-handle-progress-dialog-in.html ) und in Android-Quellen gesehen habe, scheint es die einzig mögliche Situation zu sein, dies zu erreichen Ausnahme ist, wenn die Aktivität zerstört wurde. Aber wie ich bereits erwähnt habe, verbiete ich die Erholung von Aktivitäten für grundlegende Ereignisse.
Vorschläge sind daher sehr willkommen.
Antworten:
Manchmal wird dieser Fehler auch angezeigt, wenn ich den Dialog schließe und die Aktivität mit der onPostExecute-Methode beende. Ich denke, manchmal wird die Aktivität beendet, bevor der Dialog erfolgreich beendet wird.
Einfache und dennoch effektive Lösung, die für mich funktioniert
quelle
Hier ist meine "kugelsichere" Lösung, die alle guten Antworten zusammenfasst, die ich zu diesem Thema gefunden habe (danke an @Damjan und @Kachi). Hier wird die Ausnahme nur verschluckt, wenn alle anderen Erkennungsmethoden nicht erfolgreich waren. In meinem Fall muss ich den Dialog automatisch schließen und dies ist die einzige Möglichkeit, die App vor einem Absturz zu schützen. Ich hoffe es hilft dir! Bitte stimmen Sie ab und hinterlassen Sie Kommentare, wenn Sie Anmerkungen oder eine bessere Lösung haben. Danke dir!
quelle
dialog = null
hat keine Auswirkung. UndStatusEventDialog
sollte nur lesenDialog
.isDestroyed()
verwenden möchten, falls dies nicht verfügbar ist, aber für praktische Zwecke wäre es nicht dasselbe, nur try / catch immer zu verwenden?Möglicherweise habe ich eine Problemumgehung.
Hatte das gleiche Problem, bei dem ich viele Elemente (über das Dateisystem) in ein
ListView
via ein ladeAsyncTask
. Hatte dasonPreExecute()
Auslösen einesProgressDialog
, und dann beideonPostExecute()
undonCancelled()
(aufgerufen, wenn die Aufgabe explizit über abgebrochen wirdAsyncTask.cancel()
) Schließen über.cancel()
.Ich habe den gleichen Fehler "java.lang.IllegalArgumentException: Ansicht nicht an Fenstermanager angehängt" erhalten, als ich den Dialog in der
onCancelled()
Methode von beendet habeAsyncTask
(ich hatte dies in der hervorragenden Shelves-App gesehen ).Die Problemumgehung bestand darin, ein öffentliches Feld zu erstellen, das Folgendes
AsyncTask
enthältProgressDialog
:Dann in ,
onDestroy()
wenn ich meine stornierenAsyncTask
, kann ich töten auch den zugehörigen Dialog über:Der Aufruf
AsyncTask.cancel()
auslöstonCancelled()
in demAsyncTask
, aber aus irgendeinem Grunde von der Zeit , diese Methode aufgerufen wird, wird die Ansicht bereits zerstört und damit der Dialog Cancelling versagt.quelle
Hier ist die richtige Lösung zur Lösung dieses Problems:
Anstatt alle Ausnahmen blind abzufangen, behebt diese Lösung die Ursache des Problems: Der Versuch, einen Dialog zu verkleinern, wenn die zum Initialisieren des Dialogs verwendete Aktivität bereits abgeschlossen ist. Ich arbeite an meinem Nexus 4 mit KitKat, sollte aber für alle Android-Versionen funktionieren.
quelle
isDestroyed
erfordert API 17+Ich stimme einer Meinung von 'Damjan' zu.
Wenn Sie viele Dialoge verwenden, sollten Sie alle Dialoge in onDestroy () oder onStop () schließen.
In diesem Fall können Sie möglicherweise die Häufigkeit "java.lang.IllegalArgumentException: Ausnahme, die nicht an den Fenstermanager angehängt ist" reduzieren.
aber wenig überschreiten ...
um es klarer zu machen, verhindern Sie, dass nach dem Aufruf von onDestroy ein Dialogfeld angezeigt wird.
Ich benutze nicht wie unten. aber es ist klar.
Viel Glück!
quelle
Benutze das.
quelle
if
In solchen Fällen ist es nicht erforderlich, mehrere zu verschachteln. Der Java-&&
Operator hat eine verzögerte Auswertung (auch Kurzschluss genannt), was bedeutet, dass der 2. Operand nicht ausgewertet wird, wenn der erste auswertetfalse
(was das Ergebnis von bedeutet das&&
wirdfalse
sowieso immer sein , daher "faule" auswertung). Ebenso||
wird sein 2. Operand nicht ausgewertet, wenn der erste zu ausgewertet wirdtrue
. Hinweis: Die Operatoren&
und|
haben dieses Verhalten nicht und werten daher immer beide Operanden aus.Ich hatte das gleiche Problem, Sie können es lösen durch:
quelle
Ich denke, Ihr Code ist korrekt im Gegensatz zu der anderen vorgeschlagenen Antwort. onPostExecute wird auf dem UI-Thread ausgeführt. Das ist der springende Punkt bei AsyncTask - Sie müssen sich keine Gedanken über den Aufruf von runOnUiThread machen oder sich mit Handlern befassen. Darüber hinaus kann entlassen () laut den Dokumenten sicher von jedem Thread aus aufgerufen werden (nicht sicher, ob dies die Ausnahme war).
Vielleicht ist es ein Zeitproblem, bei dem dialog.dismiss () aufgerufen wird, nachdem die Aktivität nicht mehr angezeigt wird?
Was ist mit dem Testen, was passiert, wenn Sie den setOnCancelListener auskommentieren und dann die Aktivität beenden, während die Hintergrundaufgabe ausgeführt wird? Dann versucht Ihr onPostExecute, einen bereits entlassenen Dialog zu schließen. Wenn die App abstürzt, können Sie wahrscheinlich nur überprüfen, ob der Dialog geöffnet ist, bevor Sie ihn schließen.
Ich habe genau das gleiche Problem, also werde ich es im Code ausprobieren.
quelle
Alex,
Ich könnte mich hier irren, aber ich vermute, dass mehrere Telefone in freier Wildbahn einen Fehler aufweisen, der dazu führt, dass sie bei Anwendungen, die als statisch ausgerichtet markiert sind, die Ausrichtung ändern. Dies passiert ziemlich oft auf meinem persönlichen Telefon und auf vielen Testtelefonen, die unsere Gruppe verwendet (einschließlich Droide, n1, g1, Held). Normalerweise legt sich eine App, die als statisch ausgerichtet (möglicherweise vertikal) markiert ist, für ein oder zwei Sekunden in horizontaler Ausrichtung an und wechselt dann sofort zurück. Das Endergebnis ist, dass Sie darauf vorbereitet sein müssen, auch wenn Sie nicht möchten, dass Ihre App die Ausrichtung ändert. Ich weiß nicht, unter welchen genauen Bedingungen dieses Verhalten reproduziert werden kann. Ich weiß nicht, ob es für eine Android-Version spezifisch ist. Ich weiß nur, dass ich es schon oft gesehen habe :(
Ich würde empfehlen, die in dem von Ihnen geposteten Link bereitgestellte Lösung zu verwenden , die vorschlägt, die Activity onCreateDialog-Methode zu überschreiben und das Android-Betriebssystem den Lebenszyklus Ihrer Dialoge verwalten zu lassen. Es sieht für mich so aus, als ob Sie nicht möchten, dass Ihre Aktivität die Ausrichtung wechselt, sondern irgendwo die Ausrichtung wechselt. Sie können versuchen, eine Methode aufzuspüren, die immer ein Umschalten der Ausrichtung verhindert, aber ich möchte Ihnen sagen, dass ich persönlich nicht glaube, dass es eine narrensichere Methode gibt, die auf allen aktuellen Android-Handys auf dem Markt funktioniert.
quelle
Was für mich die meiste Zeit funktioniert hat, ist zu überprüfen, ob die Aktivität nicht beendet ist.
quelle
Habe gerade das gleiche Problem. Fix für API Level 13 oder höher.
Aus Android-Dokumenten:
Also habe ich mein Manifest dahingehend geändert:
Und jetzt funktioniert es gut. Die Aktivität wird nicht wiederhergestellt, wenn ich das Telefon drehe, der Fortschrittsdialog und die Ansicht gleich bleiben. Kein Fehler für mich.
quelle
Führen Sie zunächst eine Fehlerbehandlung durch, wenn Sie versuchen, den Dialog zu schließen.
Wenn sich das nicht beheben lässt, schließen Sie es in der onStop () -Methode der Aktivität.
quelle
Ich hatte das gleiche Problem bei der Verwendung einer Schaltfläche zum Synchronisieren einer Liste vom Server: 1) Ich klicke auf die Schaltfläche. 2) Beim Herunterladen der Liste vom Server wird ein Fortschrittsdialog angezeigt. 3) Ich drehe das Gerät in eine andere Ausrichtung. 4) java.lang .IllegalArgumentException: Die Ansicht wurde während progress.dismiss () nicht an den Fenstermanager in postExecute () der AsyncTask angehängt.
Als ich das Update ausprobierte, stellte ich fest, dass meine Liste nicht alle Elemente anzeigt, auch wenn das Problem nicht auftritt.
Ich wollte, dass die AsyncTask beendet wird (und den Dialog beendet), bevor die Aktivität zerstört wird. Deshalb habe ich das asynctask-Objekt zu einem Attribut gemacht und die onDestroy () -Methode überschrieben.
Wenn die Asynctask viel Zeit in Anspruch nimmt, hat der Benutzer möglicherweise das Gefühl, dass das Gerät langsam ist, aber ich denke, das ist der Preis, den er für den Versuch zahlt, die Geräteorientierung zu ändern, während der Fortschrittsdialog angezeigt wird. Und selbst wenn es einige Zeit dauert, stürzt die App nicht ab.
quelle
quelle
Möglicherweise funktioniert der folgende Code für Sie. Er funktioniert für mich einwandfrei:
Definieren Sie Ihre Ansicht nicht global, wenn Sie sie vom Hintergrunddienst aufrufen.
quelle