Handler vs AsyncTask vs Thread [geschlossen]


382

Ich habe über die Unterschiede leicht verwirrt zwischen Handlers, AsyncTaskund Threadsin Android. Ich habe hier in StackOverflow einige Blogs und Fragen gelesen.

Handlersind Hintergrundthreads, mit denen Sie mit der Benutzeroberfläche kommunizieren können. Das Aktualisieren eines Fortschrittsbalkens sollte beispielsweise über erfolgen Handler. Die Verwendung von Handlern bietet Ihnen den Vorteil MessagingQueues, dass Sie Nachrichten planen oder mehrere Benutzeroberflächenelemente aktualisieren oder sich wiederholende Aufgaben ausführen möchten.

AsyncTasksind ähnlich, in der Tat verwenden sie Handler, werden aber nicht im UI-Thread ausgeführt, sodass es gut zum Abrufen von Daten, zum Beispiel zum Abrufen von Webdiensten, geeignet ist. Später können Sie mit der Benutzeroberfläche interagieren.

ThreadSie können jedoch nicht mit der Benutzeroberfläche interagieren, bieten "grundlegenderes" Threading und Sie vermissen alle Abstraktionen von AsyncTask.

Ich möchte jedoch, dass eine Socket-Verbindung in Betrieb genommen wird. Sollte dies in einem Handler oder einem Thread oder sogar einem ausgeführt werdenAsyncTask ? Eine Interaktion mit der Benutzeroberfläche ist überhaupt nicht erforderlich. Macht es einen Unterschied in Bezug auf die Leistung, die ich verwende?

Inzwischen wurde die Dokumentation erheblich verbessert.



9
"Handler sind Hintergrund-Threads" - Einige der am besten bewerteten Antworten scheinen auch in diese Richtung zu gehen. Aber das ist ein Missverständnis. A Handlerist kein Thread und führt nichts aus. Es ist nur ein Mittel, um Nachrichten von einem sicher weiterzuleiten Thread an die Nachrichtenwarteschlange eines anderen Threads zu übergeben . Also, in der Regel, (mindestens) zwei Fäden müssen noch erstellt werden , die dann verwenden Sie einen Handler, aber der Handler kann nicht alles selbst ausführen.
JimmyB

Antworten:


57

Als Tutorial zur Android-Hintergrundverarbeitung mit Handlern, AsyncTask und Loadern auf der Vogella-Website heißt es:

Das Handler Klasse kann zum Registrieren in einem Thread verwendet werden und bietet einen einfachen Kanal zum Senden von Daten an diesen Thread.

Das AsyncTask Klasse kapselt die Erstellung eines Hintergrundprozesses und die Synchronisation mit dem Hauptthread. Es unterstützt auch das Berichten des Fortschritts der ausgeführten Aufgaben.

Und a Threadist im Grunde das Kernelement des Multithreading, das ein Entwickler mit folgendem Nachteil nutzen kann:

Wenn Sie Java-Threads verwenden, müssen Sie die folgenden Anforderungen in Ihrem eigenen Code erfüllen:

  • Synchronisation mit dem Hauptthread, wenn Sie Ergebnisse an die Benutzeroberfläche zurücksenden
  • Keine Standardeinstellung zum Abbrechen des Threads
  • Kein Standard-Thread-Pooling
  • Keine Standardeinstellung für die Behandlung von Konfigurationsänderungen in Android

Und in Bezug auf die AsyncTask, wie die Android-Entwicklerreferenz es ausdrückt:

AsyncTaskermöglicht die ordnungsgemäße und einfache Verwendung des UI-Threads. Diese Klasse ermöglicht das Ausführen von Hintergrundoperationen und das Veröffentlichen von Ergebnissen auf dem UI-Thread, ohne dass Threads und / oder Handler bearbeitet werden müssen.

AsyncTaskausgelegt ist , eine Hilfsklasse zusammen zu sein Threadund Handler und stellt keinen allgemeinen Threading Rahmen. AsyncTasks sollten idealerweise für kurze Vorgänge (höchstens einige Sekunden) verwendet werden. Wenn Sie Threads über einen längeren Zeitraum laufen lassen müssen, wird dringend empfohlen, die verschiedenen APIs zu verwenden, die vom Paket java.util.concurrent bereitgestellt werden, z Executor, ThreadPoolExecutor und FutureTask.

Update Mai 2015: Ich habe eine hervorragende Vortragsreihe zu diesem Thema gefunden.

Dies ist die Google-Suche: Douglas Schmidt Vortrag Android Parallelität und Synchronisation

Dies ist das Video der ersten Vorlesung auf YouTube

All dies ist Teil des CS 282 (2013): Systemprogrammierung für Android von der Vanderbilt University . Hier ist die YouTube-Wiedergabeliste

Douglas Schmidt scheint ein ausgezeichneter Dozent zu sein

Wichtig: Wenn Sie an einem Punkt, wo Sie verwenden erwägen AsyncTaskIhre Threading Probleme zu lösen, sollten Sie zunächst überprüfenReactiveX/RxAndroid für ein möglicherweise geeignetere Programmiermuster. Eine sehr gute Quelle, um sich einen Überblick zu verschaffen, ist das beispielhafte Lernen von RxJava 2 für Android .


4
In dieser Vorlesungsreihe führt Sie dieser Link direkt zu einigen Thread-Beispielen: youtu.be/4Vue_KuXfCk?t=19m24s
Aggressor

353

Wenn wir uns den Quellcode ansehen, werden wir sehen AsyncTaskund er Handlerist rein in Java geschrieben. (Es gibt jedoch einige Ausnahmen. Aber das ist kein wichtiger Punkt.)

Es gibt also keine Magie in AsyncTaskoder Handler. Diese Kurse erleichtern uns das Leben als Entwickler.

Beispiel: Wenn Programm A Methode A () aufruft, kann Methode A () in einem anderen Thread mit Programm A ausgeführt werden. Wir können dies anhand des folgenden Codes leicht überprüfen:

Thread t = Thread.currentThread();    
int id = t.getId();

Warum sollten wir für einige Aufgaben einen neuen Thread verwenden? Sie können dafür googeln. Viele, viele Gründe, zB: schweres Heben, lang laufende Arbeiten.

Also, was sind die Unterschiede zwischen Thread, AsyncTaskund Handler?

AsyncTaskund Handlersind in Java geschrieben (intern verwenden sie a Thread), also alles, was wir mit Handleroder AsyncTasktun können, können wir auch mit a erreichen Thread.

Was kann Handlerund kann AsyncTaskwirklich helfen?

Der offensichtlichste Grund ist die Kommunikation zwischen dem Aufruferthread und dem Arbeitsthread. ( Caller-Thread : Ein Thread, der den Worker-Thread aufruft , um einige Aufgaben auszuführen. Ein Caller-Thread muss nicht unbedingt der UI-Thread sein.) Natürlich können wir auf andere Weise zwischen zwei Threads kommunizieren, aber aufgrund der Thread-Sicherheit gibt es viele Nachteile (und Gefahren).

Deshalb sollten wir Handlerund verwenden AsyncTask. Diese Klassen erledigen den größten Teil der Arbeit für uns. Wir müssen nur wissen, welche Methoden überschrieben werden müssen.

Der Unterschied zwischen Handlerund AsyncTaskist: Verwenden Sie diese Option,AsyncTask wenn der Caller-Thread ein UI-Thread ist . Dies ist, was Android-Dokument sagt:

AsyncTask ermöglicht die ordnungsgemäße und einfache Verwendung des UI-Threads. Diese Klasse ermöglicht das Ausführen von Hintergrundoperationen und das Veröffentlichen von Ergebnissen auf dem UI-Thread, ohne dass Threads und / oder Handler bearbeitet werden müssen

Ich möchte zwei Punkte hervorheben:

1) Einfache Verwendung des UI-Threads (also verwenden, wenn der Aufruferthread UI-Thread ist).

2) Handler müssen nicht manipuliert werden. (bedeutet: Sie können Handler anstelle von AsyncTask verwenden, AsyncTask ist jedoch eine einfachere Option.)

Es gibt viele Dinge in diesem Beitrag, die ich noch nicht gesagt habe, zum Beispiel: Was ist UI-Thread oder warum ist es einfacher. Sie müssen einige Methoden hinter jeder Klasse kennen und verwenden, Sie werden den Grund dafür vollständig verstehen.

@: Wenn Sie das Android-Dokument lesen, sehen Sie:

Mit dem Handler können Sie Nachrichten- und ausführbare Objekte senden und verarbeiten, die der MessageQueue eines Threads zugeordnet sind

Diese Beschreibung mag zunächst seltsam erscheinen. Wir müssen nur verstehen, dass jeder Thread jede Nachrichtenwarteschlange hat (wie eine Aufgabenliste), und der Thread nimmt jede Nachricht entgegen und tut dies, bis die Nachrichtenwarteschlange leer ist (genau wie wir unsere Arbeit beenden und ins Bett gehen). Also wannHandler kommuniziert wird, gibt es nur eine Nachricht an den Aufruferthread und es wartet auf die Verarbeitung.

Kompliziert? Denken Sie daran, dass Handlerdies sicher mit dem Anrufer-Thread kommunizieren kann.


4
Tatsächlich basiert Asynctask auch auf Handler und Futuretask, siehe
Sumit

AsyncTask ist im Wesentlichen eine Hilfsklasse, die auf Handler und Thread basiert. developer.android.com/reference/android/os/AsyncTask.html . Schauen Sie sich das Dokument "AsyncTask ist als Hilfsklasse für Thread und Handler konzipiert" an. AsyncTask wird in API3 freigegeben, während Handler seit API1 vorhanden ist.
Hjchin

52

Nach eingehender Betrachtung ist es einfach.

AsyncTask::

Es ist eine einfache Möglichkeit, einen Thread zu verwenden, ohne etwas über das Java-Thread-Modell zu wissen . AsyncTaskGibt verschiedene Rückrufe für den Worker-Thread und den Haupt-Thread.

Verwendung für kleine Wartevorgänge wie die folgenden:

  1. Abrufen einiger Daten von Webdiensten und Anzeigen über das Layout.
  2. Datenbankabfrage.
  3. Wenn Sie feststellen, dass der laufende Vorgang niemals verschachtelt wird.

Handler::

Wenn wir eine Anwendung in Android installieren, wird ein Thread für diese Anwendung namens MAIN UI Thread erstellt. Alle Aktivitäten werden in diesem Thread ausgeführt. Nach der Android-Single-Thread-Modellregel können wir nicht direkt auf UI-Elemente (Bitmap, Textansicht usw.) für einen anderen in dieser Aktivität definierten Thread zugreifen.

Mit einem Handler können Sie von anderen Hintergrund-Threads aus mit dem UI-Thread kommunizieren. Dies ist in Android nützlich, da Android anderen Threads nicht erlaubt, direkt mit dem UI-Thread zu kommunizieren. Ein Handler kann Message- und Runnable-Objekte senden und verarbeiten, die der MessageQueue eines Threads zugeordnet sind. Jede Handler-Instanz ist einem einzelnen Thread und der Nachrichtenwarteschlange dieses Threads zugeordnet. Wenn ein neuer Handler erstellt wird, ist er an die Thread- / Nachrichtenwarteschlange des Threads gebunden, der ihn erstellt.

Es passt am besten zu:

  1. Sie können damit Nachrichten in die Warteschlange stellen.
  2. Nachrichtenplanung.

Thread::

Jetzt ist es Zeit, über den Thread zu sprechen.

Thread ist das übergeordnete Element von AsyncTaskund Handler. Beide verwenden intern Thread, was bedeutet, dass Sie auch ein eigenes Thread-Modell wie AsyncTaskund erstellen können. Dies Handlererfordert jedoch gute Kenntnisse der Java-Implementierung für mehrere Threads .


1
Die AsyncTask-API wurde in der Tat mit Futures, Handlern und Executoren geschrieben. Siehe Quellcode: grepcode.com/file_/repository.grepcode.com/java/ext/…
IgorGanapolsky

22

An AsyncTaskwird verwendet, um Hintergrundberechnungen durchzuführen und das Ergebnis im UI-Thread zu veröffentlichen (mit optionalen Fortschrittsaktualisierungen). Da Sie sich nicht mit der Benutzeroberfläche befassen, ist a Handleroder Threadangemessener.

ThreadMit der Methode Handler's können Sie einen Hintergrund erzeugen und Nachrichten an Ihren Hauptthread zurückgeben post.


9

Faden

Android unterstützt Standard-Java- Threads . Sie können Standard-Threads und die Tools aus dem Paket " java.util.concurrent" verwenden, um Aktionen in den Hintergrund zu stellen. Die einzige Einschränkung besteht darin, dass Sie die Benutzeroberfläche nicht direkt über einen Hintergrundprozess aktualisieren können.

Wenn Sie die Benutzeroberfläche von einer Hintergrundaufgabe aus aktualisieren müssen, müssen Sie einige Android-spezifische Klassen verwenden. Sie können die Klasse " android.os.Handler" für diese oder die Klasse "" verwendenAsyncTask " verwenden

Handler

Die Klasse " Handler" kann die Benutzeroberfläche aktualisieren. Ein Handle bietet Methoden zum Empfangen von Nachrichten und für ausführbare Dateien. Um einen Handler zu verwenden, müssen Sie ihn in Unterklassen unterteilen und überschreiben handleMessage(), um Nachrichten zu verarbeiten. Zur Verarbeitung Runablekönnen Sie die Methode verwenden. post();Sie benötigen nur eine Instanz eines Handlers in Ihrer Aktivität.

Sie können Nachrichten über die Methode sendMessage(Message msg)oder posten sendEmptyMessage.

AsyncTask

Wenn Sie ActivityInhalte herunterladen oder Vorgänge ausführen müssen, die im Hintergrund ausgeführt werden AsyncTaskkönnen, können Sie eine reaktionsschnelle Benutzeroberfläche verwalten und den Fortschritt für diese Vorgänge für den Benutzer veröffentlichen.

Weitere Informationen finden Sie unter diesen Links.

http://mobisys.in/blog/2012/01/android-threads-handlers-and-asynctask-tutorial/

http://www.slideshare.net/HoangNgoBuu/android-thread-handler-and-asynctask


6

Thread::

Sie können die neue Funktion Threadfür Hintergrundaufgaben mit langer Laufzeit verwenden, ohne den UI-Thread zu beeinträchtigen. In Java Thread können Sie den UI-Thread nicht aktualisieren.

Da normaler Thread für die Android-Architektur nicht sehr nützlich ist, wurden Hilfsklassen für das Threading eingeführt.

Antworten auf Ihre Fragen finden Sie auf der Dokumentationsseite zur Threading-Leistung .

Handler :

Mit A Handlerkönnen Sie Nachrichten und RunnableObjekte senden und verarbeiten, die einem Thread zugeordnet sind MessageQueue. Jede HandlerInstanz ist einem einzelnen Thread und der Nachrichtenwarteschlange dieses Threads zugeordnet.

Es gibt zwei Hauptverwendungen für a Handler:

  1. Planen von Nachrichten und ausführbaren Dateien, die zu einem späteren Zeitpunkt ausgeführt werden sollen;

  2. So stellen Sie eine Aktion in die Warteschlange, die für einen anderen Thread als Ihren eigenen ausgeführt werden soll.

AsyncTask :

AsyncTaskermöglicht die ordnungsgemäße und einfache Verwendung des UI-Threads. Mit dieser Klasse können Sie Hintergrundoperationen ausführen und Ergebnisse auf dem UI-Thread veröffentlichen, ohne Threads und / oder Handler bearbeiten zu müssen.

Nachteile:

  1. Standardmäßig überträgt eine App alle von AsyncTaskihr erstellten Objekte in einen einzigen Thread. Daher werden sie seriell ausgeführt, und wie beim Hauptthread kann ein besonders langes Arbeitspaket die Warteschlange blockieren. Verwenden Sie aus diesem Grund AsyncTask, um Arbeitselemente mit einer Dauer von weniger als 5 ms zu verarbeiten .

  2. AsyncTaskObjekte sind auch die häufigsten Straftäter für implizite Referenzprobleme. AsyncTaskObjekte bergen auch Risiken im Zusammenhang mit expliziten Verweisen.

HandlerThread :

Möglicherweise benötigen Sie einen traditionelleren Ansatz zum Ausführen eines Arbeitsblocks in einem lang laufenden Thread (im Gegensatz zu AsyncTask, der für eine Workload von 5 ms verwendet werden sollte ) und eine gewisse Fähigkeit, diesen Workflow manuell zu verwalten. Ein Handler-Thread ist effektiv ein lang laufender Thread, der die Arbeit aus einer Warteschlange erfasst und bearbeitet.

ThreadPoolExecutor :

Diese Klasse verwaltet die Erstellung einer Gruppe von Threads, legt deren Prioritäten fest und verwaltet, wie die Arbeit auf diese Threads verteilt wird. Wenn die Arbeitslast zunimmt oder abnimmt, dreht sich die Klasse oder zerstört mehr Threads, um sich an die Arbeitslast anzupassen.

Wenn die Arbeitsbelastung höher ist und Single HandlerThreadnicht ausreicht, können Sie sich entscheidenThreadPoolExecutor

Ich möchte jedoch, dass eine Socket-Verbindung in Betrieb genommen wird. Sollte dies in einem Handler oder einem Thread oder sogar in einer AsyncTask ausgeführt werden? Eine Interaktion mit der Benutzeroberfläche ist überhaupt nicht erforderlich. Macht es einen Unterschied in Bezug auf die Leistung, die ich verwende?

Da keine UI-Interaktion erforderlich ist, können Sie sich nicht dafür entscheiden AsyncTask. Normale Threads sind nicht sehr nützlich und daher HandlerThreaddie beste Option. Da Sie die Socket-Verbindung aufrechterhalten müssen, ist der Handler im Haupt-Thread überhaupt nicht nützlich. Erstellen Sie ein HandlerThreadund erhalten Sie ein Handlervom Looper von HandlerThread.

 HandlerThread handlerThread = new HandlerThread("SocketOperation");
 handlerThread.start();
 Handler requestHandler = new Handler(handlerThread.getLooper());
 requestHandler.post(myRunnable); // where myRunnable is your Runnable object. 

Wenn Sie wieder mit dem UI-Thread kommunizieren möchten, können Sie einen weiteren Handler verwenden, um die Antwort zu verarbeiten.

final Handler responseHandler = new Handler(Looper.getMainLooper()) {
        @Override
        public void handleMessage(Message msg) {
            //txtView.setText((String) msg.obj);
            Toast.makeText(MainActivity.this,
                    "Foreground task is completed:"+(String)msg.obj,
                    Toast.LENGTH_LONG)
                    .show();
        }
    };

in Ihrem Runnablekönnen Sie hinzufügen

responseHandler.sendMessage(msg);

Weitere Details zur Implementierung finden Sie hier:

Android: Toast in einem Thread


5

Meiner Meinung nach sind Threads nicht die effizienteste Methode zum Herstellen von Socket-Verbindungen, bieten jedoch die meisten Funktionen zum Ausführen von Threads. Ich sage das, weil aus Erfahrung heraus das lange Ausführen von Threads dazu führt, dass Geräte sehr heiß und ressourcenintensiv sind. Selbst ein einfaches while(true)Telefon heizt ein Telefon in wenigen Minuten auf. Wenn Sie sagen, dass die Interaktion mit der Benutzeroberfläche nicht wichtig ist, ist eine Interaktion möglicherweise AsyncTaskgut, da sie für langfristige Prozesse ausgelegt ist. Dies ist nur meine Meinung dazu.

AKTUALISIEREN

Bitte ignorieren Sie meine obige Antwort! Ich habe diese Frage 2011 beantwortet, als ich mit Android weit weniger Erfahrung hatte als jetzt. Meine obige Antwort ist irreführend und wird als falsch angesehen. Ich lasse es dort, weil viele Leute es unten kommentiert haben, um mich zu korrigieren, und ich habe meine Lektion gelernt.

Es gibt weitaus bessere andere Antworten auf diesen Thread, aber ich werde mir zumindest die richtige Antwort geben. Es ist nichts Falsches daran, ein normales Java zu verwenden Thread. Sie sollten jedoch sehr vorsichtig sein, wie Sie es implementieren, da es sehr prozessorintensiv sein kann, wenn Sie es falsch machen (das bemerkenswerteste Symptom kann sein, dass sich Ihr Gerät aufheizt). AsyncTasks sind ideal für die meisten Aufgaben, die Sie im Hintergrund ausführen möchten (gängige Beispiele sind Festplatten-E / A, Netzwerkaufrufe und Datenbankaufrufe). Allerdings AsyncTasksollte s nicht für besonders lange Prozesse verwendet wird, müssen möglicherweise auch nach dem Benutzer Ihre Anwendung geschlossen wird oder in dem Standby setzen ihr Gerät. Ich würde für die meisten Fälle sagen, dass alles, was nicht in den UI-Thread gehört, in einem erledigt werden kannAsyncTask .


Danke, gibt es tatsächlich einen Grund, warum ich Threads anstelle von AsyncTasks verwenden sollte? Oder ist es empfehlenswerter, davon Gebrauch zu machen?
Alx

9
@AeroDroid In Ihrem Beispiel: "a simple while (true)" binden Sie die CPU hier ein, es sei denn, Sie fügen der Schleife einen Ruhezustand hinzu. Dies gilt für jede Endlosschleife. Wenn Sie die CPU-Auslastung aufgrund dieses Overheads reduzieren möchten, halten Sie den Thread am Ende der Schleife einige Millisekunden lang in den Ruhezustand.
Fehler 454

1
@ Fehler 454 - das ist interessant! Wenn Sie eine geeignete Zahl für die Schlafzeit auswählen müssten, würde sie zwischen 40 und 80 Millisekunden liegen?
Abhijit

6
@Abhijit Nach dem Spiel, das ich in SDL gemacht habe, reichte es aus, der Schleife einfach einen Schlaf von 10 ms hinzuzufügen, um im Leerlauf von 99% CPU auf ~ 0 zu fallen.
Fehler 454

15
Tatsächlich sagt developer.android.com/reference/android/os/AsyncTask.html : "AsyncTasks sollten idealerweise für KURZE Operationen verwendet werden." Sie sollten sie auch vorsichtig verwenden, da sie vom System ohne Ausführung verworfen werden können!
Typ-a1pha

5

AsyncTaskist so konzipiert, dass nicht mehr als einige Sekunden im Hintergrund ausgeführt werden (nicht empfohlen für Megabyte des Herunterladens von Dateien vom Server oder für rechenintensive CPU-Aufgaben wie Datei-E / A-Vorgänge). Wenn Sie einen lang laufenden Vorgang ausführen müssen, wird dringend empfohlen, native Java-Threads zu verwenden. Java bietet Ihnen verschiedene Thread-bezogene Klassen, um das zu tun, was Sie brauchen. Verwenden Sie Handlerdiese Option, um den UI-Thread zu aktualisieren.


2
public class RequestHandler {

    public String sendPostRequest(String requestURL,
                                  HashMap<String, String> postDataParams) {

        URL url;

        StringBuilder sb = new StringBuilder();
        try {
            url = new URL(requestURL);

            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setReadTimeout(15000);
            conn.setConnectTimeout(15000);
            conn.setRequestMethod("POST");
            conn.setDoInput(true);
            conn.setDoOutput(true);


            OutputStream os = conn.getOutputStream();
            BufferedWriter writer = new BufferedWriter(
                    new OutputStreamWriter(os, "UTF-8"));
            writer.write(getPostDataString(postDataParams));

            writer.flush();
            writer.close();
            os.close();
            int responseCode = conn.getResponseCode();

            if (responseCode == HttpsURLConnection.HTTP_OK) {
                BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream()));
                sb = new StringBuilder();
                String response;
                while ((response = br.readLine()) != null){
                    sb.append(response);
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
        return sb.toString();
    }

    private String getPostDataString(HashMap<String, String> params) throws UnsupportedEncodingException {
        StringBuilder result = new StringBuilder();
        boolean first = true;
        for (Map.Entry<String, String> entry : params.entrySet()) {
            if (first)
                first = false;
            else
                result.append("&");

            result.append(URLEncoder.encode(entry.getKey(), "UTF-8"));
            result.append("=");
            result.append(URLEncoder.encode(entry.getValue(), "UTF-8"));
        }

        return result.toString();
    }

}

1

Lassen Sie mich versuchen, die Frage hier mit einem Beispiel zu beantworten :) - MyImageSearch [Bitte beziehen Sie sich hier auf das Bild des Hauptaktivitätsbildschirms - mit einer Bearbeitungstext- / Suchschaltfläche / Rasteransicht]

MyImageSearch

Beschreibung von MyImageSearch - Sobald der Benutzer die Details in das Feld zum Bearbeiten von Text eingegeben und auf die Schaltfläche "Suchen" geklickt hat, werden Bilder im Internet über die von flickr bereitgestellten Webdienste durchsucht (Sie müssen sich nur dort registrieren, um einen Schlüssel / ein geheimes Token zu erhalten). - Für die Suche senden wir eine HTTP-Anfrage und GET JSON-Daten als Antwort zurück, die die URLs der einzelnen Bilder enthalten, die wir dann zum Laden der Rasteransicht verwenden.

Meine Implementierung - In der Hauptaktivität werde ich eine innere Klasse definieren, die die AsyncTask erweitert, um die HTTP-Anforderung in der doInBackGround-Methode zu senden, die JSON-Antwort abzurufen und meine lokale ArrayList von FlickrItems zu aktualisieren, die ich zum Aktualisieren meiner GridView über den FlickrAdapter verwenden werde (erweitert den BaseAdapter) und rufen Sie adapter.notifyDataSetChanged () in onPostExecute () von AsyncTask auf, um die Rasteransicht neu zu laden. Beachten Sie, dass hier die HTTP-Anforderung ein blockierender Aufruf ist, aufgrund dessen ich sie über die AsyncTask ausgeführt habe. Außerdem kann ich die Elemente im Adapter zwischenspeichern, um die Leistung zu erhöhen, oder sie auf der SDCard speichern. Das Raster, das ich im FlickrAdapter aufblasen werde, enthält in meiner Implementierung eine Fortschrittsanzeige und eine Bildansicht. Unten finden Sie den Code für mainActivity, den ich verwendet habe.

Antwort auf die Frage jetzt - Sobald wir die JSON-Daten zum Abrufen einzelner Bilder haben, können wir die Logik implementieren, die Bilder über Handler oder Threads oder AsyncTask in den Hintergrund zu bringen. Wir sollten hier beachten, dass meine heruntergeladenen Bilder auf der Benutzeroberfläche / im Hauptthread angezeigt werden müssen. Wir können Threads nicht einfach so verwenden, wie sie sind, da sie keinen Zugriff auf den Kontext haben. Im FlickrAdapter die Auswahlmöglichkeiten, die mir einfallen:

  • Auswahl 1: Erstellen Sie einen LooperThread [erweitert Thread] - und laden Sie weiterhin Bilder nacheinander in einem Thread herunter, indem Sie diesen Thread offen halten [looper.loop ()]
  • Auswahl 2: Verwenden Sie einen Thread-Pool und veröffentlichen Sie die ausführbare Datei über myHandler, die einen Verweis auf meine ImageView enthält. Da die Ansichten in der Rasteransicht jedoch wiederverwendet werden, kann das Problem erneut auftreten, wenn das Bild in Index 4 in Index 9 angezeigt wird [Download kann nimm dir mehr Zeit]
  • Auswahl 3 [Ich habe dies verwendet]: Verwenden Sie einen Thread-Pool und senden Sie eine Nachricht an myHandler, die Daten zum ImageView-Index und zu ImageView selbst enthält. Während handleMessage () wird ImageView daher nur aktualisiert, wenn currentIndex mit dem Index von übereinstimmt das Bild, das wir herunterladen wollten.
  • Auswahl 4: Verwenden Sie AsyncTask, um die Bilder im Hintergrund herunterzuladen, aber hier habe ich keinen Zugriff auf die Anzahl der gewünschten Threads im Thread-Pool und es variiert je nach Android-Version, aber in Auswahl 3 kann ich eine bewusste Entscheidung treffen der Größe des Thread-Pools abhängig von der verwendeten Gerätekonfiguration.

Hier der Quellcode:

public class MainActivity extends ActionBarActivity {

    GridView imageGridView;
    ArrayList<FlickrItem> items = new ArrayList<FlickrItem>();
    FlickrAdapter adapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        imageGridView = (GridView) findViewById(R.id.gridView1);
        adapter = new FlickrAdapter(this, items);
        imageGridView.setAdapter(adapter);
    }

    // To avoid a memory leak on configuration change making it a inner class
    class FlickrDownloader extends AsyncTask<Void, Void, Void> {



        @Override
        protected Void doInBackground(Void... params) {
            FlickrGetter getter = new FlickrGetter();

            ArrayList<FlickrItem> newItems = getter.fetchItems();

            // clear the existing array
            items.clear();

            // add the new items to the array
            items.addAll(newItems);

            // is this correct ? - Wrong rebuilding the list view and should not be done in background
            //adapter.notifyDataSetChanged();

            return null;
        }

        @Override
        protected void onPostExecute(Void result) {
            super.onPostExecute(result);

            adapter.notifyDataSetChanged();
        }

    }

    public void search(View view) {
        // get the flickr data
        FlickrDownloader downloader = new FlickrDownloader();
        downloader.execute();
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();
        if (id == R.id.action_settings) {
            return true;
        }
        return super.onOptionsItemSelected(item);
    }
}

Ich hoffe, dass meine lange Antwort dazu beiträgt, einige der feineren Details zu verstehen.


Darf ich den Grund kennen, warum meine Erklärung anhand eines Beispiels aus Gründen der Analogie herabgestimmt wurde, damit ich auch daraus lerne?
Akshaymani

2
Zunächst einmal vielen Dank für Ihre Antwort, auch wenn dieses Thema etwas alt ist, bleiben die Kernkonzepte immer noch auf dem neuesten Stand. Meine erste Frage wird überhaupt nicht beantwortet, Sie geben ein Beispiel und erklären, wie es funktioniert, aber die Fragen fragen nach Unterschieden zwischen Handler, Asynctask und Thread.
Alx

@ 80leaves ok, ich verstehe jetzt, ich habe versucht zu erklären, wie ich zu dem Schluss gekommen bin, einen Weg über den anderen zu wählen. Wie auch immer, würde gerne Ihre / andere Ansichten darüber hören, ob das, was ich geschrieben habe, korrekt ist oder ob es weiter verbessert werden kann.
Akshaymani

1

Es hängt davon ab, welche Sie wählen, hängt von der Anforderung ab

Der Handler wird meistens verwendet, um von einem anderen Thread zum Haupt-Thread zu wechseln. Der Handler ist an einen Looper angeschlossen, auf dem er seine ausführbare Aufgabe in die Warteschlange stellt. Wenn Sie sich bereits in einem anderen Thread befinden und zum Hauptthread wechseln, benötigen Sie ein Handle anstelle einer asynchronen Aufgabe oder eines anderen Threads

Wenn ein Handler, der in einem anderen als dem Haupt-Thread erstellt wurde, der kein Looper ist, beim Erstellen des Handles des Threads keinen Fehler ausgibt, muss dieser Thread zu einem Lopper gemacht werden

AsyncTask wird verwendet, um Code für einige Sekunden auszuführen, der im Hintergrundthread ausgeführt wird, und gibt das Ergebnis an den Hauptthread weiter. ** * AsyncTask-Einschränkungen 1. Die Async-Task ist nicht an den Lebenszyklus der Aktivität gebunden und wird auch dann ausgeführt, wenn ihre Aktivität zerstört wird, während der Loader dies nicht tut Diese Einschränkung gilt nicht. 2. Alle Async-Aufgaben verwenden denselben Hintergrundthread für die Ausführung, was sich auch auf die App-Leistung auswirkt

Der Thread wird in der App auch für Hintergrundarbeiten verwendet, hat jedoch keinen Rückruf für den Hauptthread. Wenn die Anforderung für einige Threads anstelle eines Threads geeignet ist und die mehrmals eine Aufgabe ausführen müssen, ist der Thread-Pool-Executor die bessere Option. Beispiel: Laden von Bildern aus mehreren URLs wie gleiten.


0

Faden

Wenn Sie eine App starten, wird ein Prozess zum Ausführen des Codes erstellt. Um die Rechenressourcen effizient zu nutzen, können Threads innerhalb des Prozesses gestartet werden, sodass mehrere Aufgaben gleichzeitig ausgeführt werden können. Mit Threads können Sie effiziente Apps erstellen, indem Sie die CPU ohne Leerlaufzeit effizient nutzen.

In Android werden alle Komponenten in einem einzigen Hauptthread ausgeführt. Android-Systemwarteschlangenaufgaben und führen Sie sie einzeln im Hauptthread aus. Wenn lang laufende Aufgaben ausgeführt werden, reagiert die App nicht mehr.

Um dies zu verhindern, können Sie Arbeitsthreads erstellen und Hintergrund- oder Langzeitaufgaben ausführen.

Handler

Da Android ein Single-Thread-Modell verwendet, werden UI-Komponenten nicht threadsicher erstellt. Dies bedeutet, dass nur der von ihm erstellte Thread darauf zugreifen sollte. Dies bedeutet, dass die UI-Komponente nur im Haupt-Thread aktualisiert werden sollte. Da UI-Komponenten auf dem Hauptthread ausgeführt werden, können Aufgaben, die auf Worker-Threads ausgeführt werden, UI-Komponenten nicht ändern. Hier kommt Handler ins Spiel. Der Handler kann mithilfe von Looper eine Verbindung zu einem neuen Thread oder einem vorhandenen Thread herstellen und den darin enthaltenen Code auf dem verbundenen Thread ausführen.

Der Handler ermöglicht die Kommunikation zwischen Threads. Mit dem Handler kann der Hintergrundthread Ergebnisse an ihn senden, und der mit dem Hauptthread verbundene Handler kann die UI-Komponenten im Hauptthread aktualisieren.

AsyncTask

Die von Android bereitgestellte AsyncTask verwendet sowohl Thread als auch Handler, um das Ausführen einfacher Aufgaben im Hintergrund und das Aktualisieren der Ergebnisse vom Hintergrundthread zum Hauptthread zu vereinfachen.

Beispiele finden Sie unter Android-Thread, Handler, Asynctask und Thread-Pools .


-1

Handler- ist ein Kommunikationsmedium zwischen Threads. In Android wird es meistens verwendet, um mit dem Hauptthread zu kommunizieren, indem Nachrichten über den Handler erstellt und gesendet werden

AsyncTask- wird verwendet, um lang laufende Anwendungen in einem Hintergrundthread auszuführen. Mit nAsyncTask können Sie die Operation in einem Hintergrundthread ausführen und das Ergebnis im Hauptthread der Anwendung abrufen.

Thread- ist ein leichter Prozess, um Parallelität und maximale CPU-Auslastung zu erreichen. In Android können Sie Thread verwenden, um Aktivitäten auszuführen, die die Benutzeroberfläche der App nicht berühren

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.