Verständnisfrage Asynctask und Rückgabewert

  • Hallo zusammen,


    ich habe einen Asynctask.


    Im doInBackground hole ich Daten vom Server,
    im onPostExecute schreibe ich diese in die Datenbank.


    Das funktioniert so lange ich den Rückgabewert des Asynctask nicht auswerte.
    ok = loadproducts.get(); (loadprodukts ist eine Instanz des Asynctask und der booleansche Wert wird vom doInBackground zurückgegeben )




    So wird das onPostExecute wohl gar nicht mehr ausgeführt.


    Heisst das die Rückgabe eines auswertbaren (boolean )Wertes sollte erst im onPostExecute erfolgen,
    oder sollte ich das Schreiben in die DB besser auch ins doInBackground verlagern.


    Danke für eure Meinungen.

  • Solange dein async Task irgendwas tut solltest du dich nicht um seinen Rückgabewert kümmern.
    Sobald in onPostExecute gesprungen wird, ist dein async Task fertig. Vorher nicht.


    Dein Rückgabewert landet als Parameter in der onPostExecute. Du selbst hast dich darum überhaupt nicht zu kümmern.


    Wenn du also designbedingt irgendwo außerhalb deines Async Task auf den Wert der doInBackground zugreifen musst, dann musst du dein Design überdenken.

    Je mehr Käse, desto mehr Löcher.
    Je mehr Löcher, desto weniger Käse.
    Daraus folgt: je mehr Käse, desto weniger Käse.


    »Dies ist ein Forum. Schreibt Eure Fragen in das Forum, nicht per PN!«

  • ok, das hab ich soweit verstanden,
    wozu ist dann aber loadproducts.get(); das get gedacht?
    wird das nur im onPostExecute benutzt um auf den Rückgabewert zuzugreifen ?


    was macht eigentlich der asynctask, wenn während dessen Laufzeit der User die App wieder beendet,
    sprich in meinem Fall, wird das Schreiben der DB damit unterbrochen ?


    ich wollte mit dem booleschen Wert nur prüfen ob der asynctask beendet wurde O:-)

  • Sers,


    also entweder benutze ich den AsyncTask etwas strange oder verstehe nicht, warum alle immer gerne die onPostExecute benutzen wollen ...
    Die ist wie ich verstanden habe doch dazu da, ein Ergebnis, das die doInBackground erarbeitet hat, in der GUI sichtbar zu machen. Da die Methode auf dem UI Thread ausgeführt wird kein Problem.


    Du willst ja offenbar nur überprüfen, ob das ganze geklappt hat. Warum definierst du deinen AsyncTask nicht einfach so, dass die doInBackground einen boolean liefert?


    Ein Beispiel eines Tasks von mir:


    Wird einfach so aufgerufen:


    Funktioniert einwandfrei ...



    Gruß,
    matze

  • hallo Mathias,
    so hatte ich das ja ursprünglich auch umgesetzt.
    damit scheint aber das onPostExecute() wohl nicht mehr ausgeführt zu werden.
    Ob es Sinn macht, _darin_ den Benutzer über den Erfolg der Aktion zu informieren sei mal dahingestellt.


    Hat mich eben erstaunt, dass der Tasc nach dem get() quasi beendet ist :(

  • Hoi,


    Zitat


    Runs on the UI thread after doInBackground(Params...). The specified result is the value returned by doInBackground(Params...).


    This method won't be invoked if the task was cancelled.


    vll. wird das return einem cancel gleich gesetzt ... aber schon irgendwie doof. Man möchte meinen die hätten das so wie das finally eines try-catch blocks verwirklicht. Man kann im try-catch einen Wert zurück geben via return und das finally wird trotzdem vorher noch ausgeführt ... etwas enttäuschend, dass das hier offenbar nicht auf diese Weise funktioniert.



    Gruß,
    matze

  • http://developer.android.com/r…oid/os/AsyncTask.html#get()

    Zitat

    Waits if necessary for the computation to complete, and then retrieves its result.


    Der Task wird nicht beendet, sondern es wird auf sein Ende gewartet und dann bekommst du das Resultat.
    Das bedeutet: wann immer du .get() auf deinen AsyncTask aufrufst ist dieser fertig. (Ansonsten hagelt es exceptions)


    Ja, danach wird onPostExecute nicht mehr aufgerufen, da du dir ja selbst das Ergebnis geholt hast.
    onPostExecute ist genau für derartige Fälle da: den User informieren wenn die Dinge fertig sind.
    Denn all das geschieht über das UI. Wenn man die Infos nicht braucht, implementiert man halt eine leere onPostExecute.


    Da aber gefühlt ALLE Aktionen in Android irgendwie auf diesen verfluchten UI Thread hinaus wollen gibt es nichts, was dagegen spricht.

    Je mehr Käse, desto mehr Löcher.
    Je mehr Löcher, desto weniger Käse.
    Daraus folgt: je mehr Käse, desto weniger Käse.


    »Dies ist ein Forum. Schreibt Eure Fragen in das Forum, nicht per PN!«

  • Man möchte meinen die hätten das so wie das finally eines try-catch blocks verwirklicht. Man kann im try-catch einen Wert zurück geben via return und das finally wird trotzdem vorher noch ausgeführt ... etwas enttäuschend, dass das hier offenbar nicht auf diese Weise funktioniert.


    Wieso erwartest du dieses Verhalten?
    Ich persönlich mag ja Exceptions und das damit einhergehende Handling überhaupt nicht und empfinde try-catch Blöcke als hinderlichen Steinzeitmist.
    Mein Lieblingsbeispiel: Integer.parseInt("");


    Da erwarte ich: 0
    Aber ich bekomme eine Exception – dafuq?


    Wie dem auch sei, von einem Hintergrundtask erwarte ich, dass er im Hintergrund agiert. Ich erwarte, dass er mich über seine Zustände informiert.
    Bei meinem Verständnis (ich komme wie bereits mehrfach angedeutet aus der Smalltalk/Objective-C Welt) teilen meine Objekte mir alles mit.


    Das heißt, ich frage nicht ständig: "Ey, Hintergrundtask, BIST DU BALD MA FETTICH?" sondern er sagt mir: "Hier Hintergrundtask. Habe Fertig."


    Ich frage nicht ständig: "Ey, Hintergrundtask, wie ist der Status?" und werte dann die Antworten aus um zu überlegen was ich nun tue.
    Sondern er sagt mir 'Hier Hintergrundtask. Aufgabe 1 von 245 erledigt.', 'Hier Hintergrundtask. Aufgabe 2 von 254 erledigt.", 'Hier Hintergrundtask. Bearbeitung abgebrochen.'


    Die Benutzung der Schnittstellen des AsyncTask erlaubt mir halt so etwas Ähnliches.
    "Hier Hintergrundtask. Lege gleich los." = onPreExecute.
    "Hier Hintergrundtask. Hab XYZ erledigt." = onProgressUpdate.
    "Hier Hintergrundtask. Habe fertig." = onPostExecute.
    "Hier Hintergrundtask. Habe abgebrochen." = onCancelled


    Für mich ist das genau die Art und Weise, mit der die Objekte kommunizieren sollten.
    Und wenn ich mitten drin sage "Ey Hintergrundtask, sach mir Bescheid wenn de fertig bist" (.get()), dann ist es doch ganz klar, dass der Hintergrundtask nicht noch ein zweites mal angeschissen kommt und sacht "Hier Hintergrundtask. Habe fertig."
    Denn wie oft sollte er das auch sagen?

    Je mehr Käse, desto mehr Löcher.
    Je mehr Löcher, desto weniger Käse.
    Daraus folgt: je mehr Käse, desto weniger Käse.


    »Dies ist ein Forum. Schreibt Eure Fragen in das Forum, nicht per PN!«

  • Mein Lieblingsbeispiel: Integer.parseInt("");


    Da erwarte ich: 0
    Aber ich bekomme eine Exception – dafuq?


    Also ich ärgere mich, wenn da 0 zurück kommt, obwohl ich einen Roman übergeben hatte, anstatt eine Zahl.


    Du kommst aus einer ganz anderen Sprache, joa, merkt man echt sehr stark. Aber ich persönlich finde das Exception-Handling gut, weil ich einfach sehe wo es hängt und was los ist. Selbst wenn ich die Exception nur fange und dann die Variable im catch selbst auf 0 setze, es ist schön es zu wissen, dass irgendwo ein Scheiß übergeben wurde. Vll kommt der ja auch von aussen und ich komme so auf den Ansatz dort noch eine Vor-Überprüfung zu verwirklichen ...


    Was bin ich immer wieder am fluchen wenn ich PHP mache ... da fragt man if (variableA > variableB) und wollte eigenltich if ($variableA > $variableB) haben ... dann überprüft der Held die Strings "variableA" > "variableB" und sagt nichtmal bescheid, dass da was schief läuft. Ganz zu schweigen davon, dass es keine Strings sein dürften, denn es fehlen ja Anführungszeichen ...


    Also ich für meinen Teil finde Exception-Handling und diese pervers genaue Typ-Sicherheit sehr sehr wichtig, denn sonst sucht man unter Umständen ewig nach einem 0815 Fehler, der total unnötig gewesen wäre und Java hätte dich das ganze nichtmal compilen lassen.



    Zum AsyncTask:


    Das kann man so und so sehen ... in dem Fall stört mich persönlich eigentlich nur, dass das in der API nicht besonders hervorgehoben wird, sondern man eigentlich erst durch eine logische Schlussfolgerung drauf kommt.



    Gruß,
    matze

  • Wenn ich einen String mit Scheiß übergebe und mir die Routine daraus eine Zahl bauen soll, dann ERWARTE ich, dass sie bei JEDEM String eine Zahl zurückgibt.
    Sie muss mir nicht aus "zwölf" eine 12 machen und auch nicht aus "RüdigerDie80JährigeAltePottsauStinkt" eine 80.
    Aber doch bitte aus "Hier steht keine Zahl drin, egal wie man sich dreht und wendet." eine 0.
    Eine App hat niemals nicht abzustürzen, nur weil Müll übergeben wurde!


    Vor Allem beim Beispiel "" ist 0 naheliegend. Denn "" kommt aus einem XML Element <maxtries/> und bedeutet: keine Höchstanzahl an Versuchen.


    Auch FileNotFound Exceptions finde ich sinnlos. ICH habe meine Objekte zu prüfen und nicht irgend eine Routine. Öffne ich also eine Datei, die es nicht gibt, ist das Resultat NULL.
    Niemals nicht soll die App dann einfach abstürzen, zumal 'Datei nicht vorhanden' ein Standardfall und kein schwerer Ausnahmefehler ist.
    (Fun Fact: Fange ich den Fehler ab muss ich das Resultat auf irgendwas Vernünftiges setzen, da es ja weiterhin nicht initialisiert ist – das hätte ich auch ohne Exception tun können.)


    Überhaupt habe ich das Gefühl, dass C#, Java oder C++ keine objektorientierten Sprachen sind, sondern klassenorientierte Sprachen.
    Ein Interface kann keine optionalen Methoden haben. Warum nicht?


    Konstrukte wie

    Java
    if(!callback.getIsOkayToDoSo())
    {
      callback.doSomethingElse();
    }
    else
    {
      iDoItByMyself();
    }

    sind im Allgemeinen keine Seltenheit.
    Dennoch muss meine abgeleitete Klasse selbst dann doSomethingElse() implementieren, wenn getIsOkayToDoSo() immer true zurückgibt.


    Ein weiteres Beispiel: wie erfahre ich, ob ein Objekt...? Frag seine Klasse!


    Wie erfahre ich, ob ein Objekt die Methode doSomething() implementiert? Frag seine Klasse nach den implementierten Methoden und schau nach, ob doSomething() dabei ist.
    Wie erfahre ich, ob ein Objekt das Interface CanDoSomething() implementiert? Frag seine Klasse, ob sie eine Instanz des Interface ist.
    Wie erfahre ich, ob eine Person Schreibmaschine schreiben kann? Frag ihn nach seinem Beruf und schaue nach, ob schreibmaschineSchreiben() dabei ist.


    Der Programmierer fällt raus, ebenso der Maurer. Obwohl beide es gelernt haben, der Eine in der Ausbildung, der Andere nebenbei.
    Der Schriftsteller übrigens fällt mit in die Auswahl, obwohl er seit Lebzeiten nur per Hand schreibt und nie eine Tastatur benutzt hat.


    Der richtige Weg sieht anders aus.
    Wenn du wissen willst, ob ein Objekt eine Methode implementiert, frag das Objekt, nicht seinen Bauplan.
    Wenn du wissen willst, ob ein Objekt ein Interface implementiert, frag das Objekt, nicht seinen Bauplan.
    Wenn du wissen willst, ob ein Mensch Schreibmaschine schreiben kann, frag den Menschen, nicht seinen Gesellenbrief.
    Wenn du wissen willst, ob ein Kind Hunger hat, frag das Kind, nicht seine Mama.
    Wenn du wissen willst, ob dein Flirt gut im Bett ist, frag deinen Flirt, nicht dessen Ex.
    (Oder lass dich überraschen und probiere es aus. ;))


    Im Gegensatz zum Menschen sagen die Objekte immer die Wahrheit. Das liegt allerdings darin begründet, dass bei Objekten Wahrheitstreue bei 100% und Fremdbeeinflussung bei 0% liegt.

    Je mehr Käse, desto mehr Löcher.
    Je mehr Löcher, desto weniger Käse.
    Daraus folgt: je mehr Käse, desto weniger Käse.


    »Dies ist ein Forum. Schreibt Eure Fragen in das Forum, nicht per PN!«

Jetzt mitmachen!

Sie haben noch kein Benutzerkonto auf unserer Seite? Registrieren Sie sich kostenlos und nehmen Sie an unserer Community teil!