Domanda

    

Questa domanda ha già una risposta qui:

         

Sto avendo un problema con la classe AsyncTask. Sembra mie tappe delle attività di lavoro dopo la creazione di 4 o 5 operazioni.

Im avere 2 attività. MainActivity che contiene solo un pulsante che avvia una seconda attività denominata ImageActivity.

ImageActivity è molto semplice. ha ottenuto un onCreate che imposta il layout, e poi inizia un nuovo AsyncTask che si carica un'immagine da internet. Questo funziona bene le prime volte. Ma quello che improvvisamente smette di funzionare. Il metodo OnPreExecute viene eseguito ogni volta, ma non il metodo doInBackground. Ho cercato di semplificare la doInBackground con un ciclo sonno, e la stessa cosa accade. Non riesco a capire questo behavour poiché l'AsyncTask si sia annullata e impostata nullo nel metodo OnDestroy. Così ogni volta che inizio un nuovo ImageActivity, ho anche creare un AsyncTask fresco.

I ricreare le ImageActivity e il compito premendo il tasto indietro, e poi facendo clic sul pulsante sul MainActivity.

Tutte le idee a qualcuno? Sono davvero alle prese con questo.

UPDATE: Il codice che inizia l'ImageActivity (all'interno di un pulsante di onClickListener)

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

Il codice di cui sopra inizia questa attività

    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);
    }
}

UPDATE:

Ho testato utilizzando una combinazione di Fili tradizionali e metodo runOnUiThread, e sembra funzionare meglio. Ora il filo viene eseguito ogni volta.

È stato utile?

Soluzione

Rimozione del AsyncTask e utilizzando un Discussione tradizionale , invece di combinandola con runOnUiThread sembra funzionare. Ma non ho ancora trovato il motivo per cui l'AsyncTask è così "instabile".

Ecco il codice che funziona per me:

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();
    }
}

Altri suggerimenti

Mi sono imbattuto in problema simile. Non è possibile avere più Asynctasks in esecuzione in parallelo fino SDK 11. Controllare qui per ulteriori informazioni

Ho appena incontrato questo problema pure. Se si utilizza AsyncTask.execute, il vostro compito è eseguito su una coda di serie (dalla sorgente di Android 4.3):

  

Quando la prima volta, AsyncTasks sono stati giustiziati in serie su un unico   thread in background. A partire con la ciambella, questo è stato cambiato a un pool di   discussioni consentendo più attività di operare in parallelo. Iniziare con   HONEYCOMB, compiti vengono eseguiti su un singolo filo per evitare comune   errori dell'applicazione causati da esecuzione parallela.

Questo è coerente con il comportamento che ho visto. Ho avuto un AsyncTask spuntato una finestra di dialogo in doInBackground e bloccato fino a quando la finestra è stata chiusa. La finestra aveva bisogno di un proprio AsyncTask al completo. Metodo AsyncTask.doInBackground del dialogo mai eseguito perché l'AsyncTask originale è stato ancora bloccata.

La soluzione è eseguire il secondo AsyncTask in Executor separata.

Usa Traceview per indagare - o ottenere un dump thread. La mia ipotesi è che uno dei tuoi thread AsyncTask sono appesi su download.

AsyncTask ha un piccolo pool di thread, quindi se uno dei vostri compiti si blocca, potrebbe finire per bloccare il pool di thread.

Ecco un test rapido è possibile eseguire - su 4.3, vedo che ho solo 5 thread simultanei posso correre. Quando uno thread esce, altri thread avvio.

  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);

        }
  }

Non si dovrebbe avere a preoccuparsi di filo di pulizia in Android come viene gestita dal sistema.

Si prega inoltre di inviare il metodo image scaricare. Hai provato anche di non annullare il filo nel metodo OnDestroy ()? Come stai restituendo il l'immagine al thread UI?

Il problema credo sia con l'attività di download dell'immagine pesante. Anche se si annulla l'operazione asincrona l'image scaricare continuerà ad eseguire e il compito async non finire fino a quando il download è completato. Si potrebbe voler controllare il metodo isCancelled () sul AyncTask mentre il download è in corso e uccidere il download se l'operazione viene annullata.

Per riferimento, ecco la documentazione sul annullare () Metodo: I tentativi di annullare l'esecuzione di questa operazione. Questo tentativo avrà esito negativo se l'attività è già completato, già stato cancellato, o non può essere annullato per qualche altro motivo. In caso di successo, e questo compito non è iniziato quando cancellare la si chiama, questo compito non dovrebbe mai funzionare. Se l'attività è già iniziata, allora il parametro mayInterruptIfRunning determina se il filo di eseguire questa operazione deve essere interrotta nel tentativo di fermare l'operazione. Chiamata a questo metodo si tradurrà in onCancelled (Object) viene richiamato sul thread UI dopo ritorna doInBackground (Object []). Chiamata a questo metodo garantisce che OnPostExecute (Object) non viene mai richiamato. Dopo aver invocato questo metodo, si dovrebbe verificare il valore restituito da isCancelled () periodicamente da doInBackground (Object []) per terminare l'operazione il più presto possibile.

ho avuto anche questo, nessuna vera ragione per non iniziare. Ho notato che dopo il riavvio ADB ha funzionato di nuovo. Non capisco perché questo è, ma ha funzionato per me

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top