Die Antwort von @Romain Guy ist richtig. Trotzdem möchte ich eine Ergänzung von Informationen hinzufügen und einen Zeiger auf eine Bibliothek oder 2 geben, die für AsyncTask mit langer Laufzeit und noch mehr für netzwerkorientierte Asynctasks verwendet werden können.
AsyncTasks wurden für Aufgaben im Hintergrund entwickelt. Und ja, Sie können es mit der cancelMethode stoppen . Wenn Sie Inhalte aus dem Internet herunterladen, empfehle ich Ihnen dringend, sich um Ihren Thread zu kümmern, wenn es sich um den E / A-Blockierungsstatus handelt . Sie sollten Ihren Download wie folgt organisieren:
public void download() {
while( inputStream.read(buffer) != -1 && !Thread.interrupted() ) {
}
}
Die Verwendung des Thread.interruptedFlags hilft Ihrem Thread, einen blockierenden io-Status ordnungsgemäß zu beenden. Ihr Thread reagiert schneller auf einen Aufruf der cancelMethode.
AsyncTask Designfehler
Wenn Ihre AsyncTask jedoch zu lange dauert, treten zwei verschiedene Probleme auf:
- Aktivitäten sind schlecht an den Aktivitätslebenszyklus gebunden und Sie erhalten das Ergebnis Ihrer AsyncTask nicht, wenn Ihre Aktivität stirbt. In der Tat, ja, Sie können, aber es wird der grobe Weg sein.
- AsyncTask sind nicht sehr gut dokumentiert. Eine naive, wenn auch intuitive Implementierung und Verwendung einer Asynctask kann schnell zu Speicherverlusten führen.
RoboSpice , die Bibliothek, die ich vorstellen möchte, verwendet einen Hintergrunddienst, um diese Art von Anforderungen auszuführen. Es wurde für Netzwerkanforderungen entwickelt. Es bietet zusätzliche Funktionen wie das automatische Zwischenspeichern der Ergebnisse von Anforderungen.
Hier ist der Grund, warum AsyncTasks für lange laufende Aufgaben schlecht sind. Das folgende Argument ist eine Anpassung aus Auszügen von RoboSpice-Motivationen : Die App, die erklärt, warum die Verwendung von RoboSpice einen Bedarf auf der Android-Plattform erfüllt.
Der Lebenszyklus von AsyncTask und Aktivität
AsyncTasks folgen nicht dem Lebenszyklus von Aktivitätsinstanzen. Wenn Sie eine AsyncTask innerhalb einer Aktivität starten und das Gerät drehen, wird die Aktivität zerstört und eine neue Instanz erstellt. Aber die AsyncTask wird nicht sterben. Es wird weiterleben, bis es fertig ist.
Wenn dies abgeschlossen ist, aktualisiert die AsyncTask die Benutzeroberfläche der neuen Aktivität nicht. In der Tat wird die frühere Instanz der Aktivität aktualisiert, die nicht mehr angezeigt wird. Dies kann zu einer Ausnahme vom Typ java.lang.IllegalArgumentException führen: Ansicht, die nicht an den Fenstermanager angehängt ist, wenn Sie beispielsweise findViewById verwenden, um eine Ansicht innerhalb der Aktivität abzurufen.
Speicherverlust Problem
Es ist sehr praktisch, AsyncTasks als innere Klassen Ihrer Aktivitäten zu erstellen. Da die AsyncTask die Ansichten der Aktivität bearbeiten muss, wenn die Aufgabe abgeschlossen ist oder ausgeführt wird, erscheint die Verwendung einer inneren Klasse der Aktivität praktisch: Innere Klassen können direkt auf jedes Feld der äußeren Klasse zugreifen.
Dies bedeutet jedoch, dass die innere Klasse einen unsichtbaren Verweis auf ihre äußere Klasseninstanz enthält: die Aktivität.
Auf lange Sicht führt dies zu einem Speicherverlust: Wenn die AsyncTask lange anhält, bleibt die Aktivität "am Leben", während Android sie gerne entfernen möchte, da sie nicht mehr angezeigt werden kann. Die Aktivität kann nicht durch Müll gesammelt werden. Dies ist ein zentraler Mechanismus für Android, um Ressourcen auf dem Gerät zu schonen.
Der Fortschritt Ihrer Aufgabe geht verloren
Sie können einige Problemumgehungen verwenden, um eine Asynctask mit langer Laufzeit zu erstellen und ihren Lebenszyklus entsprechend dem Lebenszyklus der Aktivität zu verwalten. Sie können die AsyncTask entweder in der onStop-Methode Ihrer Aktivität abbrechen oder Ihre asynchrone Aufgabe beenden lassen, ohne ihren Fortschritt zu verlieren und sie erneut mit der nächsten Instanz Ihrer Aktivität zu verknüpfen .
Dies ist möglich und wir zeigen, wie in RobopSpice Motivationen, aber es wird kompliziert und der Code ist nicht wirklich generisch. Darüber hinaus verlieren Sie immer noch den Fortschritt Ihrer Aufgabe, wenn der Benutzer die Aktivität verlässt und zurückkommt. Das gleiche Problem tritt bei Loadern auf, obwohl es ein einfacheres Äquivalent zu AsyncTask mit der oben erwähnten Problemumgehung für das erneute Verknüpfen wäre.
Verwenden eines Android-Dienstes
Am besten verwenden Sie einen Dienst, um Ihre lang laufenden Hintergrundaufgaben auszuführen. Und genau diese Lösung schlägt RoboSpice vor. Auch hier ist es für das Networking konzipiert, kann aber auch auf nicht netzwerkbezogene Inhalte erweitert werden. Diese Bibliothek verfügt über eine Vielzahl von Funktionen .
Dank einer Infografik können Sie sich sogar in weniger als 30 Sekunden ein Bild davon machen .
Es ist wirklich eine sehr, sehr schlechte Idee, AsyncTasks für lange laufende Vorgänge zu verwenden. Trotzdem eignen sie sich gut für kurzlebige Personen wie das Aktualisieren einer Ansicht nach 1 oder 2 Sekunden.
Ich empfehle Ihnen, die RoboSpice Motivations-App herunterzuladen. Sie erklärt dies ausführlich und bietet Beispiele und Demonstrationen der verschiedenen Möglichkeiten, netzwerkbezogene Aufgaben zu erledigen.
Wenn Sie nach einer Alternative zu RoboSpice für nicht netzwerkbezogene Aufgaben suchen (z. B. ohne Caching), können Sie sich auch Tape ansehen .