Android: AsyncTask gegen Service

138

Warum lese ich in der Antwort auf die meisten Fragen hier viel über AsyncTaskund Loader, aber nichts über Services ? Sind Services einfach nicht sehr gut bekannt oder sind sie veraltet oder haben schlechte Eigenschaften oder so? Was sind die Unterschiede?

(Übrigens weiß ich, dass es andere Themen gibt, aber keiner gibt wirklich klare Unterschiede an, die einem Entwickler helfen, leicht zu entscheiden, ob er besser dran ist, den einen oder anderen für ein tatsächliches Problem zu verwenden.)

erikbwork
quelle

Antworten:

272

In einigen Fällen ist es möglich, dieselbe Aufgabe entweder mit einer AsyncTaskoder einer zu erledigen, Servicejedoch ist normalerweise eine für eine Aufgabe besser geeignet als die andere.

AsyncTasks sind für einmalige zeitaufwändige Aufgaben konzipiert, die vom UI-Thread nicht ausgeführt werden können. Ein häufiges Beispiel ist das Abrufen / Verarbeiten von Daten, wenn eine Taste gedrückt wird.

Services sind so konzipiert, dass sie kontinuierlich im Hintergrund ausgeführt werden. Im obigen Beispiel zum Abrufen von Daten beim Drücken einer Taste können Sie einen Dienst starten, die Daten abrufen lassen und dann stoppen. Dies ist jedoch ineffizient. Es ist viel schneller, eine zu verwenden AsyncTask, die einmal ausgeführt wird, die Daten zurückgibt und fertig ist.

Wenn Sie jedoch ständig etwas im Hintergrund tun müssen, Serviceist a die beste Wahl. Beispiele hierfür sind das Abspielen von Musik, die kontinuierliche Suche nach neuen Daten usw.

Wie Sherif bereits sagte, werden Dienste nicht unbedingt über den UI-Thread ausgeführt.

Zum größten Teil sind Services für den Fall gedacht, dass Sie Code ausführen möchten, auch wenn Ihre Anwendung Activitynicht geöffnet ist. AsyncTasks wurden entwickelt, um das Ausführen von Code aus dem UI-Thread unglaublich einfach zu machen.

Computerisch
quelle
2
Es ist interessant, dass der Präsentator in diesem Vortrag von Google I / O im Jahr 2010 youtube.com/watch?v=xHXn3Kg2IQE drei verschiedene Methoden zum Abrufen von Daten von einer REST-API angibt und die erste einen Dienst verwendet. Ich bin kein Android-Experte, aber ich hatte auch den Eindruck, dass das, was Computerish sagte, grundsätzlich richtig ist.
wuliwong
10
Der letzte Absatz, "Dienste sind für den Fall vorgesehen, dass Sie Code ausführen möchten, auch wenn die Aktivität Ihrer Anwendung nicht geöffnet ist". Dies ist auch bei AsyncTask- oder Hintergrundthreads der Fall. Das heißt, wenn Sie Ihre Aktivität zurückdrücken oder finish () aufrufen und Ihre Aktivität nicht sichtbar ist, Ihre Hintergrund-Threads jedoch ausgeführt werden, bis Sie Ihren App-Prozess beenden (z. B. durch Wechseln von den letzten Aufgaben). Ich habe dies mit 4.4.2 Google Nexus AOSP Zackenbarsch
Shirish Herwade
10
AsyncTask kann jedoch schwierig sein, wenn die Aktivität, die es gestartet hat, beendet wird, während die AsyncTask noch ausgeführt wird, und die Benutzeroberfläche nach Abschluss aktualisiert werden muss ... (was nicht funktioniert, da die Aktivität bereits zerstört ist). Warum nicht einen IntentService verwenden, den Sie nicht manuell stoppen müssen, da er einfach endet, sobald er fertig ist?
AgentKnopf
tolle Punkte. Gute Erklärung zum Service. Das ist ein Service, der kontinuierlich im Hintergrund ausgeführt wird, selbst wenn die Arbeit erledigt ist.
BABU K
3
@LarsH Korrigieren Sie mich, wenn ich falsch liege, aber ich denke, Sie könnten einen BroadcastReceiver in Ihrer Aktivität / Ihrem Fragment verwenden und vom IntentService aus starten Sie einfach einen Broadcast, wenn Sie fertig sind. Da Sie sich bei der Neuerstellung von Aktivitäten / Fragmenten erneut für Broadcasts registrieren können, sollten Sie sich damit befassen. Eine andere Alternative wäre die Verwendung eines EventBus zum Aktualisieren der Benutzeroberfläche (obwohl ich versuche, diese zu vermeiden - macht es schwieriger, dem Code imo zu folgen).
AgentKnopf
58

Services sind völlig anders: Services sind keine Threads !

Ihre Aktivität ist an einen Dienst gebunden und der Dienst enthält einige Funktionen, die beim Aufruf den aufrufenden Thread blockieren. Ihr Service kann verwendet werden, um die Temperatur von Celsius auf Grad zu ändern. Jede Aktivität, die bindet, kann diesen Dienst erhalten.


Es handelt sich jedoch AsyncTaskum einen Thread, der im Hintergrund arbeitet und gleichzeitig die Möglichkeit hat, Ergebnisse an den aufrufenden Thread zurückzumelden.

Nur ein Gedanke: Ein Dienst kann ein AsyncTaskObjekt haben!

Sherif elKhatib
quelle
2
Es wird beschrieben, dass Dienste im Hintergrund ausgeführt werden und auch dann fortgesetzt werden, wenn Ihre Anwendung geschlossen ist. AsyncTask wird auch verwendet, um etwas im Hintergrund zu tun. Weißt Du, was ich meine?
Erikbwork
1
Ja, aber Dienste können etwas tun oder auch nicht. Sie sind ein langlebiges Objekt
Sherif elKhatib
"Ein Dienst hat möglicherweise ein AsyncTask-Objekt!" Vielen Dank für den Hinweis. Aber ist es eine gute Idee - würden Sie es empfehlen? Oder wäre es besser, grundlegendere Threading-Techniken in einem Dienst zu verwenden?
RenniePet
"Ihre Aktivität ist an einen Dienst gebunden" nicht unbedingt.
JacksOnF1re
@ JacksOnF1re Ich weiß, dass dies so ist, als ich mit dem Codieren anfing: p, aber "Ihre Aktivität ist an einen Dienst gebunden" ist eine wahre Aussage. Ich könnte auch für diesen Service verbindlich sein. Ein Kühlschrank könnte auch verbindlich sein. Dies macht die Aussage nicht ungültig.
Trotzdem
7

Serviceist eine der Komponenten des Android-Frameworks, für deren Ausführung keine Benutzeroberfläche erforderlich ist. Selbst wenn die App vom Benutzer nicht aktiv verwendet wird, können Sie einige Vorgänge mit dem Dienst ausführen. Das bedeutet nicht, dass der Dienst in einem separaten Thread ausgeführt wird, sondern im Hauptthread, und die Operation kann bei Bedarf in einem separaten Thread ausgeführt werden. Beispiele für die Verwendung sind das Abspielen von Musik im Hintergrund, das Synchronisieren von Daten mit dem Server im Hintergrund ohne Benutzerinteraktion usw.

AsyncTaskAuf der anderen Seite werden UI-Blockierungsaufgaben verwendet, die in einem separaten Thread ausgeführt werden. Es ist dasselbe wie das Erstellen eines neuen Threads und das Ausführen der Aufgabe, wenn alle Aufgaben zum Erstellen und Verwalten der Threads und zum Zurücksenden des Ergebnisses an den Hauptthread von der Verwendung des AsyncTask-Beispiels erledigt werden. Dabei werden Daten vom Server abgerufen, CRUD-Vorgänge auf dem Content Resolver usw.

Arjun
quelle
Können Sie angeben, warum Sie der Meinung sind, dass Ihre Antwort der Frage etwas hinzufügt?
Erikbwork
2
Andere Antworten sind entweder zu kurz oder zu lang, als dass Anfänger sie verstehen könnten. so antwortete ich genau in einfachen Worten mit Beispielen
arjun
6

Service- und Asynctask-Aufgaben tun fast dasselbe. Die Verwendung von Service oder Asynctask hängt fast davon ab, welche Anforderungen Sie stellen.

Wenn Sie beispielsweise Daten von einem Server in eine Listenansicht laden möchten, nachdem Sie eine Schaltfläche gedrückt oder den Bildschirm geändert haben, sollten Sie eine asynctask.it verwenden, die parallel zum Haupt-UI-Thread ausgeführt wird (wird im Hintergrund ausgeführt), um asynctack-Aktivitäten auszuführen, oder Ihre App sollte Auf dem Haupt-UI-Thread gibt es nach dem Beenden der App keine Asynctask.

Aber Dienste sind nicht so. Sobald Sie einen Dienst starten, kann er nach dem Beenden der App ausgeführt werden, es sei denn, Sie beenden den Dienst. Wie ich bereits sagte, hängt dies von Ihren Anforderungen ab. Wenn Sie weiterhin den Datenempfang oder den Netzwerkstatus überprüfen möchten kontinuierlich gehen Sie besser mit Service.

fröhliche Codierung.

Ashana.Jackol
quelle
1
Hallo Ashana, kann ich fragen, warum Sie diese Antwort auf eine bereits beantwortete Frage gegeben haben? Sind Sie mit der vorhandenen markierten Antwort unzufrieden? Oder versuchen Sie, ein SO-Profil zu erstellen, indem Sie Ihre Meinung zu allen Fragen schreiben, zu denen Sie etwas zu sagen haben? Oder etwas ganz anderes? Ich kann es nicht herausfinden, aber ich sehe dieses Muster in letzter Zeit ziemlich oft.
Erikbwork
3
ya ich weiß, dass die Antwort bereits gegeben ist und ich sehe hier nicht viel Problem, wenn ich die richtige Antwort oder meine Meinung hier gebe, Bruder? Da Sie nicht der einzige sind, der nach der Antwort auf dieselbe Frage sucht, kann jemand, der die Lösung in den obigen Antworten schwer versteht, nach unten scrollen, um nach einer Antwort zu suchen, die gut zu ihm passt. Verstehen Sie diese leicht. Vielen Dank für den Kommentar, Bruder, ich
bin
1

In einigen Fällen können Sie mit beiden die gleiche Funktionalität erreichen. Im Gegensatz zu Async Task hat der Service einen eigenen Lebenszyklus und erbt den Kontext (Service ist robuster als eine Async Task). Der Dienst kann auch dann ausgeführt werden, wenn Sie die App beendet haben. Wenn Sie auch nach dem Schließen der App etwas tun möchten und auch die Kontextvariable benötigen, entscheiden Sie sich für Service.

Beispiel: Wenn Sie eine Musik abspielen möchten und nicht pausieren möchten, wenn der Benutzer die App verlässt, werden Sie auf jeden Fall den Service in Anspruch nehmen.

sayem siam
quelle
1

Vergleich eines lokalen, in Bearbeitung befindlichen Basisklassendienstes ✱ mit einem AsyncTask:

✱ (Diese Antwort bezieht sich nicht auf exportierte Dienste oder Dienste, die in einem anderen Prozess als dem des Kunden ausgeführt werden, da sich die erwarteten Anwendungsfälle erheblich von denen eines unterscheiden AsyncTask. Im Interesse der Kürze auch die Art bestimmter spezialisierter Dienste ServiceUnterklassen (zB IntentService, JobService) wird hier ignoriert.)

Prozesslebensdauer

A Servicesteht für das Betriebssystem für "den Wunsch einer Anwendung, einen länger laufenden Vorgang auszuführen, ohne mit dem Benutzer zu interagieren" [ ref ].

Während Sie Servicelaufen, versteht Android, dass Sie nicht möchten, dass Ihr Prozess beendet wird. Dies gilt auch, wenn Sie einen ActivityBildschirm haben, und dies gilt insbesondere dann, wenn Sie einen Vordergrunddienst ausführen . (Wenn alle Ihre Anwendungskomponenten verschwunden sind, denkt Android: "Oh, jetzt ist ein guter Zeitpunkt, um diese App zu beenden, damit ich Ressourcen freisetzen kann.")

Abhängig vom letzten Rückgabewert von Service.onCreate()kann Android außerdem versuchen, Apps / Dienste "wiederzubeleben", die aufgrund des Ressourcendrucks beendet wurden [ ref ].

AsyncTasksTu nichts davon. Es spielt keine Rolle, wie viele Hintergrund-Threads Sie ausführen oder wie hart sie arbeiten: Android hält Ihre App nicht am Leben, nur weil Ihre App die CPU verwendet. Es muss eine Möglichkeit geben zu wissen, dass Ihre App noch Arbeit zu erledigen hat. Deshalb Servicessind sie beim Betriebssystem registriert und AsyncTasksnicht.

Multithreading

AsyncTasks Es geht darum, einen Hintergrund-Thread zu erstellen, an dem gearbeitet werden soll, und dann das Ergebnis dieser Arbeit dem UI-Thread threadsicher zu präsentieren.

Jede neue AsyncTaskAusführung führt im Allgemeinen zu mehr Parallelität (mehr Threads), vorbehaltlich der Einschränkungen des AsyncTasks'sThread-Pools [ ref ].

ServiceMethoden hingegen werden immer im UI-Thread [ ref ] aufgerufen . Dies gilt für onCreate(), onStartCommand(), onDestroy(), onServiceConnected(), etc. Also, in gewissem Sinne Servicesnicht "run" im Hintergrund. Sobald sie start ( onCreate()) sind, "sitzen" sie einfach da - bis es Zeit ist, aufzuräumen, eine auszuführen onStartCommand()usw.

Mit anderen Worten, das Hinzufügen von zusätzlichen Servicesführt nicht zu mehr Parallelität. Servicemethoden sind kein guter Ort, um viel Arbeit zu erledigen, da sie auf dem UI-Thread ausgeführt werden .

Natürlich können Sie erweitern Service, Ihre eigenen Methoden hinzufügen und sie von jedem gewünschten Thread aus aufrufen. Wenn Sie dies tun, liegt die Verantwortung für die Thread-Sicherheit bei Ihnen - nicht beim Framework.

Wenn Sie Ihrem Hintergrund einen Hintergrund-Thread (oder eine andere Art von Worker) hinzufügen möchten Service, können Sie dies tun. Sie könnten beispielsweise einen Hintergrund-Thread / AsyncTaskin starten Service.onCreate(). Dies ist jedoch nicht in allen Anwendungsfällen erforderlich. Beispielsweise:

  • Möglicherweise möchten ServiceSie weiterhin ausgeführt werden, damit Sie weiterhin Standortaktualisierungen im "Hintergrund" erhalten (dh ohne unbedingt einen ActivitiesBildschirm zu haben).
  • Oder Sie möchten Ihre App möglicherweise am Leben erhalten, damit Sie ein "implizites" BroadcastReceiverMitglied langfristig registrieren können (nach API 26 können Sie dies nicht immer über das Manifest tun, sodass Sie sich stattdessen zur Laufzeit registrieren müssen [ ref ]).

Keiner dieser Anwendungsfälle erfordert viel CPU-Aktivität. Sie verlangen lediglich, dass die App nicht getötet wird .

Als Arbeiter

Servicessind nicht aufgabenorientiert. Sie sind nicht so eingerichtet, dass sie "eine Aufgabe ausführen" und "ein Ergebnis liefern" AsyncTasks. ServicesLösen Sie keine Thread-Sicherheitsprobleme (ungeachtet der Tatsache, dass alle Methoden auf einem einzelnen Thread ausgeführt werden). AsyncTasksBehandeln Sie diese Komplexität andererseits für Sie.

Beachten Sie, dass AsyncTaskist für deprecation geplant . Aber das bedeutet nicht , Ihr sollte Ihre ersetzen AsyncTasksmit Services! (Wenn Sie aus dieser Antwort etwas gelernt haben, sollte so viel klar sein.)

TL; DR

Servicessind meistens da, um "zu existieren". Sie sind wie ein Off-Screen-Bildschirm Activityund bieten einen Grund, warum die App am Leben bleibt, während andere Komponenten sich um die "Arbeit" kümmern. AsyncTasks"arbeiten", aber sie werden an und für sich keinen Prozess am Leben erhalten.

greeble31
quelle