Ich habe viel darüber gelesen, wie ich meinen Instanzstatus speichern oder wie ich damit umgehen kann, dass meine Aktivitäten während der Bildschirmrotation zerstört werden.
Es scheint viele Möglichkeiten zu geben, aber ich habe nicht herausgefunden, welche am besten zum Abrufen der Ergebnisse einer AsyncTask geeignet ist.
Ich habe einige AsyncTasks, die einfach erneut gestartet werden und die isFinishing()
Methode der Aktivität aufrufen. Wenn die Aktivität beendet ist, werden sie nichts aktualisieren.
Das Problem ist, dass ich eine Aufgabe habe, die eine Anforderung an einen Webdienst ausführt, die fehlschlagen oder erfolgreich sein kann, und ein Neustart der Aufgabe würde zu einem finanziellen Verlust für den Benutzer führen.
Wie würden Sie das lösen? Was sind die Vor- oder Nachteile der möglichen Lösungen?
setRetainInstance(true)
auch hilfreich.Antworten:
Mein erster Vorschlag wäre, sicherzustellen, dass Ihre Aktivität tatsächlich auf einer Bildschirmdrehung zurückgesetzt werden muss (das Standardverhalten). Jedes Mal, wenn ich Probleme mit der Rotation hatte, habe ich dieses Attribut meinem
<activity>
Tag in der Datei AndroidManifest.xml hinzugefügt und war in Ordnung.Es sieht seltsam aus, aber was es bewirkt, gibt es an Ihre
onConfigurationChanged()
Methode weiter. Wenn Sie keine angeben, misst es nur das Layout neu, was die meiste Zeit eine vollkommen angemessene Methode zu sein scheint, um die Drehung zu handhaben .quelle
Unter code.google.com/p/shelves können Sie nachlesen , wie ich mit
AsyncTask
s und Orientierungsänderungen umgehe . Es gibt verschiedene Möglichkeiten, dies zu tun. Die in dieser App ausgewählte Methode besteht darin, eine aktuell ausgeführte Aufgabe abzubrechen, ihren Status zu speichern und eine neue mit dem gespeicherten Status zu starten, wenn die neueActivity
erstellt wird. Es ist einfach zu machen, es funktioniert gut und als Bonus sorgt es dafür, dass Ihre Aufgaben gestoppt werden, wenn der Benutzer die App verlässt.Sie können auch verwenden
onRetainNonConfigurationInstance()
, um IhreAsyncTask
an die neue weiterzugebenActivity
(achten Sie jedoch darauf, dass die vorherige aufActivity
diese Weise nicht verloren geht.)quelle
Dies ist die interessanteste Frage, die ich in Bezug auf Android gesehen habe !!! Eigentlich habe ich schon in den letzten Monaten nach der Lösung gesucht. Noch nicht gelöst.
Seien Sie vorsichtig und überschreiben Sie einfach die
Zeug ist nicht genug.
Betrachten Sie den Fall, wenn der Benutzer einen Anruf erhält, während Ihre AsyncTask ausgeführt wird. Ihre Anfrage wird bereits vom Server verarbeitet, sodass die AsyncTask auf eine Antwort wartet. In diesem Moment geht Ihre App in den Hintergrund, da die Telefon-App gerade in den Vordergrund getreten ist. Das Betriebssystem kann Ihre Aktivität beenden, da es sich im Hintergrund befindet.
quelle
Warum behalten Sie nicht immer einen Verweis auf die aktuelle AsyncTask auf dem Singleton bei, die von Android bereitgestellt wird?
Wann immer eine Aufgabe gestartet wird, in PreExecute oder im Builder, definieren Sie:
((Application) getApplication()).setCurrentTask(asyncTask);
Immer wenn es fertig ist, setzen Sie es auf null.
Auf diese Weise haben Sie immer eine Referenz, mit der Sie so etwas wie onCreate oder onResume ausführen können, wie es für Ihre spezifische Logik geeignet ist:
this.asyncTaskReference = ((Application) getApplication()).getCurrentTask();
Wenn es null ist, wissen Sie, dass derzeit keine ausgeführt wird!
:-)
quelle
Application
Die Instanz hat ihren eigenen Lebenszyklus - sie kann auch vom Betriebssystem beendet werden, sodass diese Lösung einen schwer zu reproduzierenden Fehler verursachen kann.Der geeignetste Weg, dies zu tun, besteht darin, ein Fragment zu verwenden, um die Instanz der asynchronen Aufgabe über Rotationen hinweg beizubehalten.
Hier ist ein Link zu einem sehr einfachen Beispiel, das es einfach macht, diese Technik in Ihre Apps zu integrieren.
https://gist.github.com/daichan4649/2480065
quelle
In
Pro android 4
. Autor hat einen schönen Weg vorgeschlagen, den Sie verwenden solltenweak reference
.Schwacher Hinweis
quelle
Aus meiner Sicht ist es besser, eine asynchrone Aufgabe zu speichern, indem Sie
onRetainNonConfigurationInstance
sie vom aktuellen Aktivitätsobjekt entkoppeln und nach der Änderung der Ausrichtung an ein neues Aktivitätsobjekt binden. Hier habe ich ein sehr schönes Beispiel gefunden, wie man mit AsyncTask und ProgressDialog arbeitet.quelle
Android: Hintergrundverarbeitung / Async Opeartion mit Konfigurationsänderung
So behalten Sie den asynchronen Zustand während des Hintergrundprozesses bei: Sie können Fragmente verwenden.
Siehe die folgenden Schritte:
Schritt 1: Erstellen Sie ein Fragment ohne Header, beispielsweise eine Hintergrundaufgabe, und fügen Sie eine private asynchrone Aufgabenklasse hinzu.
Schritt 2 (optionaler Schritt): Wenn Sie einen Ladecursor auf Ihre Aktivität setzen möchten, verwenden Sie den folgenden Code:
Schritt 3: Implementieren Sie in Ihrer Hauptaktivität die in Schritt 1 definierte BackgroundTaskCallbacks-Schnittstelle
}}
quelle
Zu berücksichtigen ist, ob das Ergebnis der AsyncTask nur für die Aktivität verfügbar sein soll, mit der die Aufgabe gestartet wurde. Wenn ja, dann ist Romain Guys Antwort am besten. Wenn es für andere Aktivitäten Ihrer Anwendung verfügbar sein soll,
onPostExecute
können Sie es verwendenLocalBroadcastManager
.Sie müssen auch sicherstellen, dass die Aktivität die Situation korrekt behandelt, wenn die Übertragung gesendet wird, während die Aktivität angehalten wird.
quelle
Schauen Sie sich diesen Beitrag an . In diesem Beitrag führt AsyncTask einen Betrieb mit langer Laufzeit und einen Speicherverlust durch, wenn die Bildschirmdrehung in einer Beispielanwendung erfolgt. Die Beispiel-App ist in der Quellschmiede verfügbar
quelle
Meine Lösung.
In meinem Fall habe ich eine Kette von AsyncTasks mit demselben Kontext. Die Aktivität hatte nur Zugriff auf die erste. Um eine laufende Aufgabe abzubrechen, habe ich Folgendes getan:
Aufgabe
doInBackground()
:Aktivität
onStop()
oderonPause()
:quelle
quelle
Sie können auch Android hinzufügen: configChanges = "keyboardHidden | orientierung | screenSize"
Zu Ihrem offensichtlichen Beispiel hoffe ich, dass es hilft
quelle