Android AsyncTask-Kontextverhalten

Ich arbeite mit AsyncTasks in Android und habe ein Problem.

Nehmen Sie ein einfaches Beispiel, eine Aktivität mit einer AsyncTask. Die Aufgabe im Hintergrund macht nichts Spektakuläres, sie schläft nur 8 Sekunden lang.

Am Ende der AsyncTask in der onPostExecute () -Methode setze ich nur einen Schaltflächensichtbarkeitsstatus auf View.VISIBLE, um meine Ergebnisse zu überprüfen.

Dies funktioniert so lange, bis der Benutzer beschließt, die Ausrichtung seines Telefons zu ändern, während die AsyncTask ausgeführt wird (innerhalb des 8-Sekunden-Ruhezustandsfensters).

Ich verstehe den Android-Aktivitätslebenszyklus und weiß, dass die Aktivität zerstört und neu erstellt wird.

Hier kommt das Problem ins Spiel. Die AsyncTask verweist auf eine Schaltfläche und enthält anscheinend einen Verweis auf den Kontext, mit dem die AsyncTask ursprünglich gestartet wurde.

Ich würde erwarten, dass dieser alte Kontext (da der Benutzer eine Orientierungsänderung verursacht hat) entweder Null wird und die AsyncTask eine NPE für den Verweis auf die Schaltfläche wirft, die sichtbar gemacht werden soll.

Stattdessen wird kein NPE ausgelöst. Die AsyncTask geht davon aus, dass die Schaltflächenreferenz nicht null ist, und setzt sie auf sichtbar. Das Ergebnis? Auf dem Bildschirm passiert nichts!

Aktualisieren: Ich habe das in Angriff genommen, indem ich aWeakReference auf die Aktivität und Umschaltung bei einer Konfigurationsänderung. Das 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 auszuführen, und ändern Sie während der Ausführung von AsyncTask die Ausrichtung Ihres Telefons.

Antworten auf die Frage(4)

Ihre Antwort auf die Frage