Ich habe mit AsyncTasks in Android gearbeitet und ich habe ein Problem.Android AsyncTask Kontextverhalten
Nehmen Sie ein einfaches Beispiel, eine Aktivität mit einer AsyncTask. Die Aufgabe im Hintergrund macht nichts Spektakuläres, sie schläft nur für 8 Sekunden.
Am Ende der AsyncTask in der onPostExecute() -Methode setze ich nur einen Button-Sichtbarkeitsstatus auf View.VISIBLE, nur um meine Ergebnisse zu überprüfen.
Jetzt funktioniert das großartig, bis der Benutzer entscheidet, die Ausrichtung seines Telefons zu ändern, während die AsyncTask funktioniert (innerhalb des 8-Sekunden-Schlaffensters).
Ich verstehe die Android-Aktivität Lebenszyklus und ich weiß, dass die Aktivität zerstört und neu erstellt wird.
Dies ist, wo das Problem auftritt. Die AsyncTask verweist auf eine Schaltfläche und enthält offenbar einen Verweis auf den Kontext, der die AsyncTask an erster Stelle gestartet hat.
Ich würde erwarten, dass dieser alte Kontext (seit der Benutzer eine Orientierungsänderung verursacht) entweder null wird und die AsyncTask eine NPE für den Verweis auf die Schaltfläche, die es sichtbar machen möchte, zu werfen.
Stattdessen wird keine NPE ausgelöst, die AsyncTask denkt, dass die Schaltflächenreferenz nicht null ist, und legt sie auf visible fest. Das Ergebnis? Nichts passiert auf dem Bildschirm!
Update: Ich habe dies angegangen, indem ich eine WeakReference
auf die Aktivität und schalten, wenn eine Konfiguration ändert passiert. Dies ist umständlich.
Hier ist der Code:
public class Main extends Activity {
private Button mButton = null;
private Button mTestButton = null;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mButton = (Button) findViewById(R.id.btnStart);
mButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
new taskDoSomething().execute(0l);
}
});
mTestButton = (Button) findViewById(R.id.btnTest);
}
private class TaskDoSomething extends AsyncTask<Long, Integer, Integer>
{
@Override
protected Integer doInBackground(Long... params) {
Log.i("LOGGER", "Starting...");
try {
Thread.sleep(8000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return 0;
}
@Override
protected void onPostExecute(Integer result) {
Log.i("LOGGER", "...Done");
mTestButton.setVisibility(View.VISIBLE);
}
}
}
Versuchen Sie es ausführen und während der AsyncTask arbeitet Ihre Telefone Orientierung ändern.
ein bisschen irreführend zu schreiben "eine WeakReference auf die Aktivität zu halten" und als es nicht im Code tun. Schlimmer noch, weiter sagst du "und schalt, wenn eine Konfigurationsänderung passiert", was wirklich nichts bedeutet ... Was schalten? – Ewoks