Threads Android AysncTask => Überprüfen, ob ein Ergebniss schon vorliegt

Naxon89

Mitglied
Moin zusammen,

mal wieder eine typische Anfängerfrage: Wie kann ich wirklich abfragen, ob der Async Task schon fertig ist?

En detail:

Ich möchte gerne Informationen aus einer Datenbank einer globalen Liste hinzufügen. Dazu benutze ich eine Klasse Download, welche die Klasse AsyncTask erweitert (siehe Snippet 1). Nachdem dieser Download und das Hinzufügen des Ergebnis an die globale Liste erfolgt ist, soll nun dieser Scanner geschlossen werden und die globale Liste in der ListActivity angezeigt werden (siehe Snippet 2). Mein Problem dabei ist nun, dass der Scanner sich manchmal vor dem Empfang des Ergebniss beendet und die ListActivity aufruft. Dazu wird dann folgende Fehlermeldung ausgeben:

W/System: A resource failed to call end.

Anschließend beendet sich APP.

Folgendes habe ich schon erfolglos versucht:
  • die Methode getNextView() entsprechend im Downloader auszuführen
  • eine globale Variable semaphore (boolean) zu verwenden

Ich hoffe, ihr könnt mir einen Tipp geben. Sollten noch Angaben fehlen, kann ich diese selbstverständlich nachreichen. Ich habe den Code hier nur gekürzt wiedergegeben, damit der Fokus auf dieses Problem gerichtet wird.

Viele Grüße aus dem Ruhrgebiet

Tobias

Snippet 1:
[CODE lang="java" title="Download.java"]

public class Download extends AsyncTask<Void, Integer, String> {

...

// receiveData beeihaltet an der Stelle 0 den Status und an der Stelle 2 das Ergebnis der Abfrage als JSON
// Im Fehlerfall muss ein leerer String zurückgegeben werden
@Override
protected String doInBackground(Void... voids) {
try{
List<String> tmp = this.receiveData.getResponse();
if(tmp.get(0).equals("200")){ // Emfang der Daten ist korrekt
return tmp.get(2);
}else{
return "";
}
}catch(Exception e){
return "";
}
}

//Überprüfung, wann der Async Task fertig ist
@Override
protected void onPostExecute(String s) {
//Notwendig, da JSONArray ein String im JSON Format benötigt
try {
//Es wird das erste Ergebnis der SQL selktiert.
JSONObject jsonObject = new JSONArray(s).getJSONObject(0);
//Hinzufügen des Elements entsprechend der Definition der Klasse Tools
TOOL_LIST.add(new Tools(
jsonObject.getString("Bezeichnung"),
this.barcode,
SELECTED_USER.getpNumber(),
new Date()
));
// Ausführen des Garbage Collector
System.gc();
// Bestätigung, dass das Hinzufügen erfolgreich ist
System.out.println("ADDING: " + s);
}catch(Exception e){
//Ausgabe etwaiger Fehler (zB String ist nicht in JSON Notation)
System.out.println("Failed: " + e.getMessage());
}
finally {
semaphore = false;
}
}
}

[/CODE]

Snippet 2:
[CODE lang="java" title="ScannerActivity"]public class ScannerActivity extends AppCompatActivity {

...


private void getNextView() throws Exception {
//Der Downloader wird initalisiert
DownloadTools downloadTools = new DownloadTools();
//Der Hintergrundprozess führt den Download duch und speichert das Ergebnis in die Variable res
String res= downloadTools.execute().get();
//Das Ergebniss des Downloads wird aufgerufen
System.out.println("Tool adding is finished: " + res);
//Die nächste Acitivity wird aufgerufen
openNextPage();
}

@Override
public void onBackPressed(){
Intent intent = new Intent(this, MainActivity.class);
this.finish();
startActivity(intent);
}

private void openNextPage(){
Intent intent = new Intent(this, ListActivity.class);
this.finish();
startActivity(intent);
}
}[/CODE]
 
Hallo

Beim Asynctast ist es so das die "doInBackground" Methode in einenm Thread ausgeführt wird. Wenn der beendet ist wird automatisch die "onPostExecute" Methode aufgerufen. Also die Methode wird immer am ende des Threads aufgerufen und die Methode wird im UI Thread ausgeführt.
Wenn du also willst das dein "openNextPage()" am Ende des Threads ausgeführt wird gehört das dort hin.
Nicht in der Main nach dem Aufruf des Task.

Das was du in der Activity nach den execute aufrufst wird unabhängig was der Task macht sofort ausgeführt. Es wird nicht auf den Thread gewartet.
Die Variable res und das get macht bei AsyncTask keinen sinn.
Dafür hast du die onPostExecute Methode.


Was in deinen Code nicht stimmen kann ist. In der Activity rufst du das auf
DownloadTools downloadTools = new DownloadTools();

Dein Asynctask heißt aber
„Download“ also das ist nicht der gleiche Task den du in der Activity startest.




Bemerken möchte ich auch das AsyncTask ab API 30 deprecated ist.
 
Zuletzt bearbeitet:
Vielen Dank für deine Antwort

Beim Asynctast ist es so das die "doInBackground" Methode in einenm Thread ausgeführt wird. Wenn der beendet ist wird automatisch die "onPostExecute" Methode aufgerufen. Also die Methode wird immer am ende des Threads aufgerufen und die Methode wird im UI Thread ausgeführt.
Wenn du also willst das dein "openNextPage()" am Ende des Threads ausgeführt wird gehört das dort hin.
Nicht in der Main nach dem Aufruf des Task.
Das ist mir durchaus bewusst und war auch mein erster Ansatz. Leider hat dies das Problem auch nicht gelöst.

Dein Asynctask heißt aber
„Download“ also das ist nicht der gleiche Task den du in der Activity startest.
Das sind nur Ausschnitte aus meinem Source Code, da ich noch mehrere Methoden habe. Die Methode, die AsyncTask erweitert, heißt DownloadTools

Bemerken möchte ich auch das AsyncTask ab API 30 deprecated ist.
Soll ich statt AsyncTask besser auf Callable wechseln? Quelle: stack overflow
 
Wie kann ich wirklich abfragen, ob der Async Task schon fertig ist?
UI-Programmierung ist im Grundsatz immer ereignisorientiert und man sollte tunlichst jeden Versuch unterlassen, von diesem Paradigma abzuweichen - gerade unter Android.

globale Variable semaphore
Globaler, veränderlicher Zustand ist praktisch immer Mist - gerade unter Android.

Android hat den netten Effekt, dass es praktisch jede Activity zu jeder Zeit "killen" kann, das gleiche gilt für die ganze Application. Wenn man das nicht bedenkt, sorgt man regelmäßig für Überraschungen (=Abstürze). Dafür hat das System aber auch ganz klar definierte Lebenszyklen.

Zur Warnung "W/System: A resource failed to call end.": da sagt mir meine Glaskugel, dass Du einen Stream der HTTP-Connection nicht geschlossen hast.
 

Neue Themen


Zurück
Oben