711 Stimmen

AsyncTask Android Beispiel

Ich las gerade über AsyncTask und ich habe das folgende einfache Programm ausprobiert. Aber es scheint nicht zu funktionieren. Wie kann ich es zum Laufen bringen?

public class AsyncTaskActivity extends Activity {

    Button btn;

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        btn = (Button) findViewById(R.id.button1);
        btn.setOnClickListener((OnClickListener) this);
    }

    public void onClick(View view){
        new LongOperation().execute("");
    }

    private class LongOperation extends AsyncTask<String, Void, String> {
        @Override
        protected String doInBackground(String... params) {
            for(int i=0;i<5;i++) {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
            TextView txt = (TextView) findViewById(R.id.output);
            txt.setText("Executed");
            return null;
        }

        @Override
        protected void onPostExecute(String result) {
        }

        @Override
        protected void onPreExecute() {
        }

        @Override
        protected void onProgressUpdate(Void... values) {
        }
    }
}

Ich versuche gerade, die Beschriftung nach 5 Sekunden im Hintergrundprozess zu ändern.

Dies ist mein main.xml :

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="fill_parent"
              android:layout_height="fill_parent"
              android:orientation="vertical" >
    <ProgressBar
        android:id="@+id/progressBar"
        style="?android:attr/progressBarStyleHorizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:indeterminate="false"
        android:max="10"
        android:padding="10dip">
    </ProgressBar>
    <Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Start Progress" >
    </Button>
    <TextView android:id="@+id/output"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Replace"/>
</LinearLayout>

850voto

Suragch Punkte 420096

Meine vollständige Antwort lautet aquí aber hier ist ein erklärendes Bild, um die anderen Antworten auf dieser Seite zu ergänzen. Für mich war es am Anfang am verwirrendsten zu verstehen, wohin all die Variablen gehen.

enter image description here

716voto

Graham Smith Punkte 25377

Ok, Sie versuchen, über einen anderen Thread auf die GUI zuzugreifen. Dies ist in der Regel keine gute Praxis.

Die AsyncTask führt alles aus, was in doInBackground() innerhalb eines anderen Threads, der keinen Zugriff auf die grafische Benutzeroberfläche hat, in der sich Ihre Ansichten befinden.

preExecute() y postExecute() bieten Ihnen Zugriff auf die grafische Benutzeroberfläche, bevor und nachdem die schwere Arbeit in diesem neuen Thread stattfindet, und Sie können sogar das Ergebnis der langen Operation an postExecute() um dann die Ergebnisse der Verarbeitung anzuzeigen.

Sehen Sie sich diese Zeilen an, in denen Sie später Ihre TextView aktualisieren:

TextView txt = findViewById(R.id.output);
txt.setText("Executed");

Legen Sie sie in onPostExecute() .

Sie werden dann sehen, dass Ihr TextView-Text nach der Aktualisierung der doInBackground komplettiert.

Mir ist aufgefallen, dass Ihr onClick-Listener nicht überprüft, welche Ansicht ausgewählt wurde. Ich finde, der einfachste Weg, dies zu tun ist über switch-Anweisungen. Ich habe eine vollständige Klasse unten mit allen Vorschlägen bearbeitet, um Verwirrung zu vermeiden.

import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.provider.Settings.System;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.view.View.OnClickListener;

public class AsyncTaskActivity extends Activity implements OnClickListener {

    Button btn;
    AsyncTask<?, ?, ?> runningTask;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        btn = findViewById(R.id.button1);

        // Because we implement OnClickListener, we only
        // have to pass "this" (much easier)
        btn.setOnClickListener(this);
    }

    @Override
    public void onClick(View view) {
        // Detect the view that was "clicked"
        switch (view.getId()) {
        case R.id.button1:
            if (runningTask != null)
                runningTask.cancel(true);
            runningTask = new LongOperation();
            runningTask.execute();
            break;
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        // Cancel running task(s) to avoid memory leaks
        if (runningTask != null)
            runningTask.cancel(true);
    }

    private final class LongOperation extends AsyncTask<Void, Void, String> {

        @Override
        protected String doInBackground(Void... params) {
            for (int i = 0; i < 5; i++) {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    // We were cancelled; stop sleeping!
                }
            }
            return "Executed";
        }

        @Override
        protected void onPostExecute(String result) {
            TextView txt = (TextView) findViewById(R.id.output);
            txt.setText("Executed"); // txt.setText(result);
            // You might want to change "executed" for the returned string
            // passed into onPostExecute(), but that is up to you
        }
    }
}

77voto

bbedward Punkte 6148

Ich bin mir sicher, dass es richtig ausgeführt wird, aber Sie versuchen, die UI-Elemente im Hintergrund-Thread zu ändern, und das geht nicht.

Ändern Sie Ihren Aufruf und Ihre AsyncTask wie folgt:

Klasse anrufen

Note : Ich persönlich empfehle die Verwendung von onPostExecute() wo Sie Ihren AsyncTask-Thread ausführen und nicht in der Klasse, die AsyncTask selbst erweitert. Ich denke, es macht den Code einfacher zu lesen, vor allem, wenn Sie die AsyncTask an mehreren Stellen benötigen und die Ergebnisse leicht unterschiedlich sind.

new LongThread() {
    @Override public void onPostExecute(String result) {
        TextView txt = (TextView) findViewById(R.id.output);
        txt.setText(result);
    }
}.execute("");

LongThread-Klasse (erweitert AsyncTask):

@Override
protected String doInBackground(String... params) {
    for (int i = 0; i < 5; i++) {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    return "Executed";
}

64voto

Nitesh Tiwari Punkte 4692

Konzept und Code hier

Ich habe ein einfaches Beispiel für die Verwendung von AsyncTask von Android erstellt. Es beginnt mit onPreExecute(), doInBackground(), publishProgress() und schließlich onProgressUpdate() .

Dabei arbeitet doInBackground() als Hintergrund-Thread, während andere im UI-Thread arbeiten. Sie können in doInBackground() nicht auf ein UI-Element zugreifen. Die Reihenfolge ist die gleiche wie ich erwähnt habe.

Wenn Sie jedoch ein Widget aus doInBackground können Sie publishProgress から doInBackground die Folgendes aufrufen wird onProgressUpdate um Ihr UI-Widget zu aktualisieren.

class TestAsync extends AsyncTask<Void, Integer, String> {
    String TAG = getClass().getSimpleName();

    protected void onPreExecute() {
        super.onPreExecute();
        Log.d(TAG + " PreExceute","On pre Exceute......");
    }

    protected String doInBackground(Void...arg0) {
        Log.d(TAG + " DoINBackGround", "On doInBackground...");

        for (int i=0; i<10; i++){
            Integer in = new Integer(i);
            publishProgress(i);
        }
        return "You are at PostExecute";
    }

    protected void onProgressUpdate(Integer...a) {
        super.onProgressUpdate(a);
        Log.d(TAG + " onProgressUpdate", "You are in progress update ... " + a[0]);
    }

    protected void onPostExecute(String result) {
        super.onPostExecute(result);
        Log.d(TAG + " onPostExecute", "" + result);
    }
}

Nennen Sie es in Ihrer Aktivität so:

new TestAsync().execute();

Entwickler-Referenz hier

22voto

Ted Hopp Punkte 227177

Verschieben Sie diese beiden Zeilen:

TextView txt = (TextView) findViewById(R.id.output);
txt.setText("Executed");

aus der AsyncTask doInBackground Methode und legen Sie sie in der onPostExecute Methode. Ihr AsyncTask sollte in etwa so aussehen:

private class LongOperation extends AsyncTask<String, Void, String> {

    @Override
    protected String doInBackground(String... params) {
        try {
            Thread.sleep(5000); // no need for a loop
        } catch (InterruptedException e) {
            Log.e("LongOperation", "Interrupted", e);
            return "Interrupted";
        }
        return "Executed";
    }      

    @Override
    protected void onPostExecute(String result) {               
        TextView txt = (TextView) findViewById(R.id.output);
        txt.setText(result);
    }
}

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X