2012-08-24 15 views
9

Ich habe einige Fragen fast identisch mit meinen gesehen, aber ich konnte keine vollständige Antwort finden, die alle meine Zweifel erfüllt. Also hier bin ich .. Angenommen, Sie haben eine Aktivität mit einer inneren Klasse, die die AsyncTask Klasse erweitert AngenommenWas passiert mit einer AsyncTask, wenn die Startaktivität gestoppt/zerstört wird, während sie noch ausgeführt wird?

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

, dass die Aktivität angehalten oder zerstört (vielleicht die beiden Fälle unterschiedlich sind), während die DownloadImageTask noch im Hintergrund läuft .. dann, die DownloadImageTask ‚s Methoden, die auf die Aktivität UI-Thread ausgeführt werden: dies wie kann ausgelöst werden und die DownloadImageTask kann versuchen, auf Activity-Methoden zuzugreifen (es ist eine innere Klasse, so dass sie auf die Methoden und Instanzvariablen der äußeren Klasse zugreifen kann) mit einer pausierten oder zerstörten Aktivität, wie der Aufruf an findViewByID im Beispiel unten .. was passiert dann? Scheitert es im Stillen? Gibt es eine Ausnahme? Wird der Benutzer benachrichtigt, dass etwas schief gelaufen ist?

Wenn wir darauf achten sollten, dass der Launch-Thread (die Aktivität in diesem Fall) noch aktiv ist, wenn Running-on-UI-Methoden aufgerufen werden, wie können wir das innerhalb der AsyncTask erreichen?

Es tut mir leid, wenn Sie dies als eine doppelte Frage finden, aber vielleicht ist diese Frage ein bisschen mehr gelenkig und kann jemand mit ausführlicher beantworten

+1

Wenn Sie diesen Code ausgeführt haben, ist es im Hintergrund fehlgeschlagen, hat eine Ausnahme ausgelöst oder dem Benutzer mitgeteilt, dass etwas schief gelaufen ist? – CommonsWare

+0

Ich habe noch keinen solchen Code ausgeführt, ich werde es die nächsten Tage tun .. Ich habe mich gefragt, bevor ich in der Implementierung meiner App weitermache. Ich werde diesen Beitrag aktualisieren, sobald ich einen Test durchführen kann.Danke @CommonsWare –

+1

Mein Punkt ist, dass das Verhalten undokumentiert ist, insbesondere angesichts der Tatsache, dass wir nichts anderes in der Aktivität sehen. 'findViewById()' könnte 'null' für' R.id.img' zurückgeben oder nicht. Und dieses Verhalten könnte von Gerät zu Gerät variieren, basierend auf der Android OS-Version, Änderungen des Geräteherstellers und ROM-Mods. – CommonsWare

Antwort

3

Betrachten Sie diese Aufgabe (wo R.id.test auf eine bezieht sich gültig Blick in das Layout meiner Tätigkeit des):

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

Wenn ich diese Aufgabe aus einer Tätigkeit des onCreate laufen wie folgt:

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

Egal, wie lange schlafen ich den Hintergrund Gewinde, mein Log zeigt immer:

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

was zu sagen ist, dass die Aktivität und seine Ansichten erscheinen am Leben zu bleiben (auch wenn ich manuell GCs über DDMS Ausgabe). Wenn ich mehr Zeit hätte, würde ich in einem Speicherabbild aus, aber sonst keine wirklich weiß ich nicht, warum dies der Fall ist ... aber in Antwort auf Ihre Fragen scheint es, dass:

  • es Does lautlos versagen? Nein
  • Gibt es eine Ausnahme? Nein
  • Wird der Benutzer benachrichtigt, dass etwas schief gelaufen ist? Keine
+0

Die Aktivität ist möglicherweise noch vorhanden, da Ihre innere Klasse einen Verweis darauf hat, aber wie sieht es mit den Sichten und den darin enthaltenen Instanzvariablen aus? – user412759

+0

Deshalb habe ich eine WeakReference zu Activity verwendet, um sicherzustellen, dass meine innere Klasse nicht der Grund dafür war, dass Activity am Leben gehalten wurde. Was Sichten und Instanzvariablen betrifft, hat meine innere Klasse keine außer der WeakReference to Activity. Außer du meinst etwas anderes? mehr auf WeakReference: http://developer.android.com/reference/java/lang/ref/WeakReference.html – newbyca

+3

@newbyca Wenn 'LongTaskTest' tatsächlich eine innere Klasse ist, dann hat es einen impliziten Verweis auf Aktivität, die Sie vergessen - machen Sie es zu einer statischen geschachtelten Klasse: http://stackoverflow.com/questions/70324/java-inner-class-and-static-nested-class – MattJenko

2

Die doInBackground() auf Laufen halten, auch wenn Sie Ihre Aktivität zerstört wird (i, e Ihr Haupt-Thread zerstört wird), weil der doInBackground() -Methode auf dem/Hintergrund-Thread des Arbeitnehmers läuft. Beim Ausführen der onPostExecute() -Methode wird ein Problem auftreten, wenn sie im main-/UI-Thread ausgeführt wird und Sie möglicherweise in nicht verwandte Daten geraten, aber dem Benutzer wird keine Ausnahme angezeigt. Daher ist es immer besser, Ihre AsyncTask abzubrechen, wenn Ihre Aktivität zerstört wird, da es keinen Grund gibt, AsyncTask auszuführen, wenn die Aktivität nicht mehr vorhanden ist. Verwenden Sie den Android-Dienst, wenn Sie ständig etwas aus dem Netzwerk herunterladen möchten, selbst wenn Ihre Komponente/Aktivität zerstört wird. Vielen Dank.

Verwandte Themen