Activity soll auf (Async)Task warten

  • Antworten:9
-drago-
  • Forum-Beiträge: 4

10.11.2016, 09:17:47 via Website

Hallo Leute,

ich habe eine Anwendung, welche nach dem Klick auf den Button "Daten Laden" Daten aus einer Datenbank im Netzwerk lädt und diese anschließend in der selben Activity anzeigen soll.
Dazu wird ein Layout mit verschiedenen TextViews "visible" geschaltet. Ich habe für die Datenbankabtrage einen AsyncTask genutzt, welcher auch einen ProgressDialog anzeigen soll. Dies Funktioniert auch alles soweit, jedoch möchte ich, dass die Activity auf den Ladeprozess und ProgressDialog wartet, bis er das Layout mit den gewünschten Infos hat.
Wenn ich die Abfragen in die Methode onPreExecute() packe, dann wartet die Activity bis diese fortfährt, aber dann erhalten ich keine Ladeanzeige, diese kommt erst bei der Methode doInBackground.

Diesen Ablauf benötige ich auch für noch weitere Ähnliche Zwecke. Ist mein Ansatz dafür mit dem AsyncTask falsch?

Antworten
swa00
  • Forum-Beiträge: 3.704

10.11.2016, 09:34:33 via Website

Hallo Drago,

ohne den genauen Quellcode ist es auch für uns schwer genau nachzuvollziehen , was du letztendlich gebastelt
hast.
Vorweg : AsyncTask sollte nur für kurze Operationen eingesetzt werden , also für ein Download eher ungeeignet.
Darüber hinaus blockiert dir ein AsyncTask Einiges.
Auf den PreExecute zu warten ist schon mal richtig , aber nur um der MainActivity mitzuteilen , dass du fertig bist oder ggf. einen CallBack ausführen .
Innerhalb des Threads solltest du ggf. mit runOnUIThread arbeiten

Ab API > 21 solltest du auch bei einem AsyncTask executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR) verwenden.

— geändert am 10.11.2016, 10:12:38

Liebe Grüße - Stefan
[ App - Entwicklung ]

-drago-

Antworten
-drago-
  • Forum-Beiträge: 4

10.11.2016, 10:16:34 via Website

Danke für die rasche Antwort.
Der Aufruf erfolgt in der Activity durch:

Button.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View arg0) {
            loadingTask = new LoadingTask<String, Void, Void>(MainActivity.this,"Loading","Daten werden geladen... Bitte warten",MainActivity.this);
            loadingTask.execute();

            TextView nameTextView = (TextView) findViewById(R.id.customArea_Name);
            nameTextView.setText(selectedName);
            customArea.setVisibility(View.VISIBLE);
            }

}

Die LoadingTast sieht wie folgt aus:

public class LoadingTask<T,G,V> extends AsyncTask<T,String,V> {

ProgressDialog progress;
Context context;
String progressTitle;
String progressText;
ILoadingTask<T,V> TaskClass;
private V resultValue;

public LoadingTask(Context context, String progressTitle, String progressText, ILoadingTask<T, V> task) {
    this.context = context;
    this.progressTitle = progressTitle;
    this.progressText = progressText;
    this.TaskClass = task;
}

@Override
protected void onPreExecute() {
    super.onPreExecute();
    progress = new ProgressDialog(context);
    progress.setMessage(progressText);
    progress.setTitle(progressTitle);

    try {
        progress.show();
    } catch (Exception ex) {
        Log.e("1" , ex.getMessage());
    }
}

/**
 * Updating progress bar
 * */
protected void onProgressUpdate(String... progressState) {
    // setting progress percentage
    progress.setProgress(Integer.parseInt(progressState[0]));
}

@Override
protected V doInBackground(T... ps) {

    // Datenbankabfragen

    V result = TaskClass.task(ps);
    resultValue = result;
    return result;
}

@Override
protected void onPostExecute(V v) {
    super.onPostExecute(v);
    progress.dismiss();
    TaskClass.setResult(resultValue);
}

}

Antworten
swa00
  • Forum-Beiträge: 3.704

10.11.2016, 10:26:47 via Website

Hallo drago,

dein Grundgerüst sieht nicht schlecht aus - Einiges ist aber nicht konkludent.
Kann es sein , dass du aus dem C/C++ Bereich kommst ???

Folgende Dinge sind mir aufgefallen :

a) Ich weis nicht was du in der TaskClass machst, von welchem Typ ist die denn ??
b) du "verschachtelst" mehrere Klassen innerhalb des AsyncTasks , das muss i.d.R. schief gehen.
c) ist deine TaskClass irgendwie statisch ? - wenn ja , kann das nicht klappen
d) Ändere den Start in deinem OnClick . (siehe oben)

Und letztendlich kann ich noch immer nicht ersehen , was dein Problem ist
Was bedeutet : "Wartet nicht ?"

— geändert am 10.11.2016, 10:29:33

Liebe Grüße - Stefan
[ App - Entwicklung ]

Antworten
swa00
  • Forum-Beiträge: 3.704

10.11.2016, 10:43:54 via Website

Ich kürze es mal ab ...

Du solltest natürlich kein AsyncTask verwenden, das hatte ich ja schon oben erwähnt.
Wenn du keine abstrusen Daten auf deinem Server besitzt , so gibt es wunderschöne Bibliotheken , die dir den
ganzen Mist abnehmen und dir ein wunderschönes Callback ( mit progressbar) auf den Tisch legen .

Schau mal z.b. hier

https://github.com/koush/ion

— geändert am 10.11.2016, 10:45:14

Liebe Grüße - Stefan
[ App - Entwicklung ]

Antworten
-drago-
  • Forum-Beiträge: 4

10.11.2016, 10:50:01 via Website

Nein ich komme nicht vom C/C++ Bereich, Programmiere in Java.
Ich habe damals diese Klasse in einem Forum gefunden und angepasst. TaskClass ist ein Interface:

public interface ILoadingTask<T,V> {
    public V task(T... ts);
    public void setResult(V value);

}

Genau das meine ich. Der AsyncTask ist hier der falsche Ansatz für mein Einsatzgebiet. Ich brauche nur eine Art Ladeanzeige "Bitte Warten" für den Benutzer dass da noch was passiert und die App nicht Abgestürzt ist.
Wie bezeichnet man sowas, was ich brauche? Ich schau mir die Bibliotheken gleich mal an und probiere diese aus.

— geändert am 10.11.2016, 10:51:05

Antworten
swa00
  • Forum-Beiträge: 3.704

10.11.2016, 10:58:03 via Website

Du musst bei Android unter Java umdenken .

Deine Ladeanzeige kannst du auch ganz einfach umsetzen , indem du einfach mit einem runOnUIThread
z.b. auf ein Progress UI Element während dem onDoBackground wurschtelst.

Und eine statische klasse mit public interface ILoadingTask { kannst du nicht so verwenden,
da diese nicht wartet , bis sie fertig ist , sondern sofort wieder zurückkommt.

Logisch , dass du sofort ein postExecute bekommst

— geändert am 10.11.2016, 10:58:51

Liebe Grüße - Stefan
[ App - Entwicklung ]

Antworten
-drago-
  • Forum-Beiträge: 4

10.11.2016, 11:09:56 via Website

runOnUIThread dann auch in einem AsyncTask ausführen?

Wäre es sinnvoll die AsyncTask komplett neu Aufzubereiten bzw. das Interface ILoadingTask zu entfernen - wie gesagt, das war damals eine Vorlage aus dem Internet und es scheint ja auch nicht so sauber zu sein.

Antworten
swa00
  • Forum-Beiträge: 3.704

10.11.2016, 11:16:04 via Website

nööö , iss ein wenig veraltet :-)

hier mal ein runOnUiThread Beispiel für dich .....

@Override
    protected Void doInBackground(Void... params)
    {
       while (DoIrgendwas == true)
       {
         // MachIrgendwas
        mActivity.runOnUiThread(new Runnable()
        {
            public void run()
            {
              MyTextView.setText ("ZEIG MICH AN ");
            }
        });
      }
       return null;
    }

— geändert am 10.11.2016, 12:20:56

Liebe Grüße - Stefan
[ App - Entwicklung ]

Antworten
Rafael K.
  • Forum-Beiträge: 2.359

12.11.2016, 10:06:01 via Website

-drago-

runOnUIThread dann auch in einem AsyncTask ausführen?

Wäre es sinnvoll die AsyncTask komplett neu Aufzubereiten bzw. das Interface ILoadingTask zu entfernen - wie gesagt, das war damals eine Vorlage aus dem Internet und es scheint ja auch nicht so sauber zu sein.

Das sollte man sich auf gar keinen Fall angewöhnen!
Genau dafür gibt es doch im AsyncTask die Methode onProgressUpdate(). Die arbeitet im Kontext des UI-Thread und kann daher OHNE diesen Umweg auf UI-Elemente zugreifen.
Man muss nur innerhalb von doInBackground() immer mal wieder publishProgress() aufrufen, damit man einen Fortschritt an die o.g. Methode weitergibt.

Antworten