2012-08-24 9 views
9

Ho visto poche domande quasi identiche alle mie, ma non sono riuscito a trovare una risposta completa che soddisfi tutti i miei dubbi .. eccomi qui .. Supponiamo che tu abbia un'attività con una classe interiore che estende la classe AsyncTask in questo modo:Cosa succede a un AsyncTask quando l'attività di avvio viene arrestata/distrutta mentre è ancora in esecuzione?

public class MyActivity extends Activity {    
    private class DownloadImageTask extends AsyncTask<String, Void, Bitmap> { 
     protected Bitmap doInBackground(String... urls) { 
      return DownloadImage(urls[0]); 
     } 
     protected void onPostExecute(Bitmap result) { 
      ImageView img = (ImageView) findViewById(R.id.img); 
      img.setImageBitmap(result); 
     } 
    } 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.main); 
     new DownloadImageTask().execute("http://mysite.com/image.png") 
    } 
} 

Supponiamo che l'attività è in pausa o distrutta (forse i due casi sono diversi), mentre il DownloadImageTask è ancora in esecuzione in background .. poi, i metodi DownloadImageTask 's che corrono sul filo di attività UI può essere attivato e il DownloadImageTask può provare ad accedere ai metodi di Activity (è una classe interna, quindi può accedere ai metodi e alle variabili di istanza della classe esterna) con un'attività in pausa o distrutta, come la chiamata a findViewByID nell'esempio seguente .. cosa succede allora? Fallisce silenziosamente? Produce qualche eccezione? L'utente verrà avvisato che qualcosa è andato storto?

Se dovremmo fare attenzione che il thread di avvio (l'attività in questo caso) sia ancora attivo quando vengono richiamati i metodi di esecuzione dell'interfaccia utente, come possiamo farlo all'interno dello AsyncTask?

Mi dispiace se si trova questo come una domanda duplicato, ma forse questa domanda è un po 'più articolata e qualcuno può rispondere con maggiore dettaglio

+1

Quando si eseguiva questo codice, si è verificato un errore silenzioso, generato un'eccezione o segnalato all'utente se qualcosa non funzionava correttamente? – CommonsWare

+0

Non ho ancora eseguito questo codice, lo farò nei prossimi giorni. Mi stavo chiedendo prima di procedere con l'implementazione della mia app. Aggiornerò questo post non appena posso eseguire un test.Grazie @CommonsWare –

+1

Il mio punto è che il comportamento non è documentato, in particolare dato che non stiamo vedendo nient'altro nell'attività. 'findViewById()' potrebbe restituire 'null' per' R.id.img', oppure no. E questo comportamento potrebbe teoricamente variare da dispositivo a dispositivo, in base alla versione del SO Android, alle modifiche del produttore del dispositivo e alle mod ROM. – CommonsWare

risposta

3

Considerate questo Task (dove R.id.test si riferisce a un vista valida nel layout della mia attività):

public class LongTaskTest extends AsyncTask<Void, Void, Void>{ 
    private WeakReference<Activity> mActivity; 
    public LongTaskTest(Activity a){ 
     mActivity = new WeakReference<Activity>(a); 
    } 
    @Override protected Void doInBackground(Void... params) { 
     LogUtil.d("LongTaskTest.doInBackground()"); 
     SystemClock.sleep(5*60*1000); 
     LogUtil.d("mActivity.get()==null " + (mActivity.get()==null)); 
     LogUtil.d("mActivity.get().findViewById(R.id.frame)==null " + (mActivity.get().findViewById(R.id.test)==null)); 
     return null; 
    } 
} 

Se corro questo compito da onCreate di un'attività in questo modo:

public class Main extends Activity { 
    @Override 
    public void onCreate(Bundle state) { 
     super.onCreate(state); 
     setContentView(R.layout.testlayout); 
     new LongTaskTest(this).execute(); 
     finish(); 
    } 
} 

Non importa quanto tempo dormo lo sfondo filo, il mio registro mostra sempre:

LongTaskTest.doInBackground() 
mActivity.get()==null false 
mActivity.get().findViewById(R.id.frame)==null false 

Vale a dire che l'attività e le sue opinioni sembrano rimanere in vita (anche se io emetto manualmente GC via DDMS). Se avessi avuto più tempo avrei guardare un dump di memoria, ma per il resto non so davvero perché questo è il caso ... ma in risposta alle vostre domande sembra che:

  • lo fa fallire silenziosamente? No
  • Produce qualche eccezione? No
  • L'utente riceverà una notifica che qualcosa è andato storto? No
+0

L'attività potrebbe essere ancora presente perché la tua classe interna ha un riferimento ad essa, ma che ne dici delle viste e delle variabili di istanza al suo interno? – user412759

+0

Ecco perché ho usato WeakReference to Activity ... per garantire che la mia classe interna non fosse la ragione per cui Activity è stata mantenuta in vita. Per quanto riguarda le viste e le variabili di istanza, la mia classe interiore non ne ha nessuna, ad eccezione di WeakReference to Activity. A meno che tu non intenda qualcos'altro? altro su WeakReference: http://developer.android.com/reference/java/lang/ref/WeakReference.html – newbyca

+3

@newbyca Se infatti 'LongTaskTest' è una classe interna, quindi ha un riferimento implicito all'Attività che ti stai dimenticando - rendilo una classe nidificata statica: http://stackoverflow.com/questions/70324/java-inner-class-and-static-nested-class – MattJenko

2

DoInBackground() continuerà a essere in esecuzione anche se l'attività viene distrutta (i, e il thread principale viene distrutto) perché il metodo doInBackground() viene eseguito sul thread worker/background. Ci sarà un "problema" nell'esecuzione del metodo onPostExecute() mentre viene eseguito sul thread principale/dell'interfaccia utente e potrebbe verificarsi l'esecuzione di dati non correlati, ma non ci sarà alcuna eccezione mostrata all'utente. Pertanto, è sempre meglio annullare AsyncTask quando l'attività viene distrutta in quanto non vi è alcun motivo per eseguire AsyncTask quando l'attività non è più presente. Usa il servizio Android se desideri scaricare continuamente qualcosa dalla rete anche quando il tuo componente/attività viene distrutto. Grazie.

Problemi correlati