wake-up-neo.com

AsyncTask doInBackground wird nicht ausgeführt

Ich habe ein Problem mit der AsyncTask-Klasse. Es scheint, als würde meine Aufgabe nach dem Erstellen von 4 oder 5 Aufgaben aufhören zu arbeiten. 

Ich habe 2 Aktivitäten. Hauptaktivität, die nur eine Schaltfläche enthält, die eine zweite Aktivität namens ImageActivity startet.

ImageActivity ist sehr einfach. es hat ein onCreate erhalten, das das Layout festlegt, und dann wird eine neue AsyncTask gestartet, die ein Bild aus dem Internet lädt. Dies funktioniert die ersten Male gut. Aber dann hört es plötzlich auf zu arbeiten. Die onPreExecute-Methode wird jedes Mal ausgeführt, nicht jedoch die doInBackground-Methode. Ich habe versucht, doInBackground mit einer Schlafschleife zu vereinfachen, und dasselbe passiert. Ich kann dieses Verhalten nicht verstehen, da die asynctask in der onDestroy-Methode sowohl abgebrochen als auch auf null gesetzt wird. Jedes Mal, wenn ich eine neue ImageActivity starte, erstelle ich auch eine neue AsyncTask.

Ich stelle die ImageActivity und die Aufgabe wieder her, indem Sie auf die Schaltfläche "Zurück" klicken und dann auf die Schaltfläche in der Hauptaktivität klicken.

Irgendwelche Ideen? Ich kämpfe wirklich mit diesem hier.

UPDATE: Code, mit dem ImageActivity gestartet wird (innerhalb einer Schaltfläche onClickListener)

Intent intent = new Intent();
intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
intent.setClassName(this, ImageActivity.class.getName());
startActivity(intent);

Der obige Code startet diese Aktivität

    public class ImageActivity extends Activity {

    private AsyncTask<Void, Void, Void> task;

    public void onCreate(Bundle bundle) {
        super.onCreate(bundle);
        setContentView(R.layout.main);

        task = new AsyncTask<Void, Void, Void>() {

            @Override
            protected void onPreExecute()
            {
                Log.d(TAG, "onPreExecute()");
            }

            @Override
            protected Void doInBackground(Void... params)
            {
                Log.d(TAG, "doInBackground() -- Here is the download");
                // downloadBitmap("http://mydomain.com/image.jpg")
                return null;
            }

            @Override
            protected void onPostExecute(Void res)
            {
                Log.d(TAG, "onPostExecute()");
                if(isCancelled()){
                    return;
                }
            }
        }.execute();
    }

    @Override
    protected void onDestroy()
    {
        super.onDestroy();
        task.cancel(true);
    }
}

AKTUALISIEREN:

Ich habe mit einer Kombination aus traditionellen Threads und der runOnUiThread-Methode getestet, und es scheint besser zu funktionieren. Jetzt läuft der Thread jedes Mal.

33
Vidar Vestnes

Das Entfernen der AsyncTask und das Verwenden eines traditional Thread anstelle der Kombination mit runOnUiThread scheint zu funktionieren. Aber ich habe immer noch nicht den Grund gefunden, warum die AsyncTask so "instabil" ist.

Hier ist der Code, der für mich funktioniert:

public class ImageActivity extends Activity {

    private Thread worker;

    public void onCreate(Bundle bundle) {
        super.onCreate(bundle);
        setContentView(R.layout.main);

        worker = new Thread(new Runnable(){

            private void updateUI(final List<Object> list)
            {
                if(worker.isInterrupted()){
                    return;
                }
                runOnUiThread(new Runnable(){

                    @Override
                    public void run()
                    {
                        // Update view and remove loading spinner etc...
                    }
                });
            }

            private List<Object> download()
            {
                // Simulate download
                SystemClock.sleep(1000);
                return new ArrayList<Object>();
            }

            @Override
            public void run()
            {
                Log.d(TAG, "Thread run()");
                updateUI(download());
            }

        });
        worker.start(); }

    @Override
    protected void onDestroy()
    {
        super.onDestroy();
        worker.interrupt();
    }
}
23
Vidar Vestnes

Ich bin auf ein ähnliches Problem gestoßen. Es können nicht mehrere Asynctasks bis SDK 11 parallel ausgeführt werden. Überprüfen Sie hier für weitere Informationen

7
ericwjr

Ich bin auch auf dieses Problem gestoßen. Wenn Sie AsyncTask.execute verwenden, wird Ihre Aufgabe in einer seriellen Warteschlange (von der Android 4.3-Quelle) ausgeführt:

Bei der ersten Einführung wurden AsyncTasks seriell auf einem einzelnen .__ ausgeführt. Hintergrund-Thread. Beginnend mit DONUT wurde dies in einen Pool von .__ geändert. Threads, die die parallele Ausführung mehrerer Tasks ermöglichen. Beginnen mit HONEYCOMB, Tasks werden in einem einzelnen Thread ausgeführt, um allgemeines .__ zu vermeiden. Anwendungsfehler durch parallele Ausführung.

Dies stimmt mit dem Verhalten überein, das ich gesehen habe. Ich hatte eine AsyncTask-Dialogbox in doInBackground und wurde blockiert, bis der Dialog geschlossen wurde. Der Dialog benötigte ein eigenes AsyncTask. Die AsyncTask.doInBackground-Methode des Dialogs wurde nie ausgeführt, da das ursprüngliche AsyncTask noch gesperrt war.

Die Lösung ist, das zweite AsyncTask in einem separaten Executor auszuführen.

6
Heath Borders

Verwenden Sie traceview zum Untersuchen - oder zum Erstellen eines Threaddumps. Meine Vermutung ist, dass einer Ihrer AsyncTask-Threads beim Herunterladen hängt.

AsyncTask verfügt über einen kleinen Thread-Pool. Wenn also eine Ihrer Aufgaben hängen bleibt, kann dies dazu führen, dass der Thread-Pool blockiert wird.

Hier ist ein kurzer Test, den Sie ausführen können - auf 4.3 habe ich nur 5 gleichzeitige Threads, die ich ausführen kann. Wenn ein Thread beendet wird, starten andere Threads.

  private void testAsyncTasks() {

        for (int i = 1; i <= 10; i++) {
              final int tid = i;
              new AsyncTask<Integer, Void, Void>() {
                    protected void onPreExecute() {
                          Log.d("ASYNCTASK", "Pre execute for task : " + tid);
                    };

                    @Override
                    protected Void doInBackground(Integer... args) {
                          int taskid = args[0];
                          long started = SystemClock.elapsedRealtime();
                          Log.d("ASYNCTASK", "Executing task: " + taskid + " at " + started);
                          for (int j = 1; j <= 20; j++) {
                                Log.d("ASYNCTASK", "   task " + taskid + ", time=" + (SystemClock.elapsedRealtime() - started));
                                SystemClock.sleep(1000);
                          }
                          return null;
                    }

                    protected void onPostExecute(Void result) {
                          Log.d("ASYNCTASK", "Post execute for task : " + tid);
                    };
              }.execute(i);

        }
  }
1
DustinB

Das Problem, das ich glaube, liegt in der schweren Aufgabe beim Herunterladen von Bildern. Selbst wenn Sie den asynchronen Task abbrechen, wird der Bilddownload weiterhin ausgeführt, und der asynchrone Task wird erst abgeschlossen, wenn der Download abgeschlossen ist. Möglicherweise möchten Sie die isCancelled () - Methode von AyncTask überprüfen, während der Download ausgeführt wird, und den Download abbrechen, wenn die Task abgebrochen wird.

Hier finden Sie die Dokumentation zur Methode cancel (): Versucht, die Ausführung dieser Task abzubrechen. Dieser Versuch schlägt fehl, wenn die Aufgabe bereits abgeschlossen ist, bereits abgebrochen wurde oder aus einem anderen Grund nicht abgebrochen werden konnte. Wenn dies erfolgreich war und diese Task beim Aufruf von cancel nicht gestartet wurde, sollte diese Task niemals ausgeführt werden. Wenn die Task bereits gestartet ist, bestimmt der Parameter mayInterruptIfRunning, ob der Thread, der diese Task ausführt, unterbrochen werden soll, um die Task zu stoppen. Wenn Sie diese Methode aufrufen, wird onCancelled (Object) nach doInBackground im UI-Thread aufgerufen (Objekt []) kehrt zurück. Der Aufruf dieser Methode garantiert, dass onPostExecute (Object) niemals aufgerufen wird. Nach dem Aufrufen dieser Methode sollten Sie den von isCancelled () zurückgegebenen Wert regelmäßig von doInBackground (Object []) überprüfen, um die Task so früh wie möglich zu beenden.

0
habib

Sie sollten sich keine Sorgen um den Housekeeping-Thread in Android machen, da dieser vom System verwaltet wird.

Bitte posten Sie auch die Methode zum Herunterladen von Bildern. Haben Sie auch versucht, den Thread in der onDestroy () -Methode nicht abzubrechen? Wie bringen Sie das Image an Ihren UI-Thread zurück?

0

Ich hatte auch dies, keinen wirklichen Grund, nicht anzufangen. Ich habe bemerkt, dass es nach dem Neustart von adb wieder funktioniert hat. Nicht sicher, warum das so ist, aber es hat für mich funktioniert

0
Alex