Android-Programmierung Background
Willemers Informatik-Ecke
Der Haupt-Thread einer App sollte sich auf die Oberfläche konzentrieren. Alle längeren Tätigkeiten wie Datei-, Datenbank- oder Netzwerkzugriffe sollten in den Hintergrund gestellt werden. Dafür bietet Android mehrere Techniken.

AsyncTask

Die Klasse AsyncTask ermöglicht es, einen Ablauf in den Hintergrund zu stellen.

Sie erstellen eine eigene AsyncTask, indem Sie AsyncTask erweitern. Sie erhält dabei drei Generics-Parameter (auch Typ-Parameter genannt), die für

  1. Eingabeparameter
  2. Fortschrittsmeldungswerte
  3. Rückgabewert
gesetzt werden.

import android.os.AsyncTask;

public class MeinAsyncTask extends AsyncTask {

    @Override
    protected Integer doInBackground(String... parameter) {
    }

    @Override
    protected void onProgressUpdate(Integer... progress) {
    }

    @Override
    protected void onPostExecute(Integer result) {
    }
}
Sie können dann folgende Methoden überschreiben: Eine Instanz einer eigenen AsyncTask kann über deren Methode execute aufgerufen werden. Dabei erhält sie den Parameter der als erster Typ-Parameter (Generics) bei der Definition der AsyncTask-Klasse angegeben wurde. Eine Instanz kann nur einmal per execute aufgerufen werden.
MeinAsyncTask async = new MeinAsyncTask();
String param[] = { "http://www.willemer.de/index.htm"};
async.execute(param);
Jedes Objekt einer AsyncTask kann nur einmal per execute aufgerufen werden. Wird eine zweite Ausführung benötigt, muss ein neues Objekt erzeugt werden, ansonsten droht eine Exception.

Rückgabe der Ergebnisse

Häufig möchte man die Ergebnisse der Hintergrundjobs weiterverwenden. Dazu kann man beispielsweise einen Callback hinterlegen, der nach Ende der Aufgabe aufgerufen wird.

Als Beispiel dient die selbstdefinierte Klasse HttpAsyncTask, die AsyncTask erweitert. Sie soll über ein selbstdefiniertes Interface HttpAsyncAntwort den Interessenten aufrufen. In diesem Fall ist es die Activity selbst.

public class HttpAsyncTask extends AsyncTask {

    private HttpAsyncAntwort httpAntwort = null;
    public HttpAsyncTask(HttpAsyncAntwort callback) { 
        httpAntwort = callback;
    }

    private String antwort = "";
Die Referenz auf das Antwort-Interface wird dem Konstruktor übergeben, damit das aufzurufende Objekt gespeichert werden kann. Das Interface ist folgendermaßen realisiert:
public interface HttpAsyncAntwort {
    public void eventAntwort(String str);
}
Der Rückruf wird in der Methode onPostExecute realisiert.
public class HttpAsyncTask extends AsyncTask {

    // ...

    @Override
    protected String doInBackground(String... parameter) {
        // ...
        return antwort;
    }

    @Override
    protected void onPostExecute(String result) {
        this.httpAntwort.eventAntwort(antwort);
        result = this.antwort;
    }
}
Die AsyncTask wird von der MainActivity aus erzeugt und aufgerufen.
public class MainActivity extends AppCompatActivity
                        implements HttpAsyncAntwort {

    TextView tv;

    // ...
    HttpAsyncTask asyncTask = new HttpAsyncTask(this);
    String url = // ...
    asyncTask.execute(url);
    // ...

    @Override
    public void eventAntwort(String str) {
        if (tv!=null) {
            tv.setText(str);
        }
    }

Link

HandlerThread

private HandlerThread handlerThread;
private Handler handler;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    handlerThread = new HandlerThread("MeinHandlerThread");
    handlerThread.start();
    handler = new Handler(handlerThread.getLooper());
}

@Override
public void onDestroy() {
    super.onDestroy();
    handlerThread.quitSafely();
}
Der HandlerThread wird mit den folgenden Zeilen aus dem Haupt-Thread gestartet.
handler.post(new Runnable() {
    public void run() {
        // Das geht alles im Hintergrund
    }
});

Auf den UI-Thread zugreifen

Wenn ein Hintergrund-Thread wieder auf die Oberfläche zugreifen will, kann es ein Runnable über die Methode runOnUiThread mit Zugriff auf den UI-Thread starten, der dann auf die Elemente der Activity zugreifen kann.
runOnUiThread(new Runnable() {
    @Override
    public void run() {
        textView.setText(antwort);
    }
});

Rückmeldung über Observer

Auf dem Wege eines Observers kann sich eine Activity bei einem Hintergrund-Thread als Interessent für Änderungen anmelden. Auf diesem Weg kann eine Activity auf das Ende eines Tasks reagieren, ohne darauf warten zu müssen.