Frage

Ich habe mit AsyncTasks in Android zu arbeiten und ich mit einem Problem zu tun habe.

Nehmen Sie ein einfaches Beispiel, eine Aktivität mit einem AsyncTask. Die Aufgabe auf dem Hintergrund nicht etwas Spektakuläres tun, es schläft nur 8 Sekunden.

Am Ende des AsyncTask im OnPostExecute () Methode, die ich gerade bin eine Schaltfläche Sichtbarkeit Status View.VISIBLE Einstellung, nur meine Ergebnisse zu überprüfen.

Nun, dies funktioniert gut, bis der Benutzer entscheidet, seine Telefon Orientierung zu ändern, während die AsyncTask arbeiten (innerhalb der 8 Sekunden Schlaf Fenster).

ich die Android-Aktivität Lebenszyklus verstehen, und ich weiß, dass die Aktivität zerstört wird und neu erstellt werden.

Dies ist, wo das Problem kommt in. Die AsyncTask auf eine Schaltfläche beziehen und halten offenbar einen Verweis auf den Kontext, der die AsyncTask in erster Linie begonnen.

Ich würde erwarten, dass dieser alte Kontext (da der Benutzer eine Orientierungsänderung verursacht) entweder wurden null und die AsyncTask eine NPE für den Hinweis auf die Schaltfläche werfen es versucht, sichtbar zu machen.

Stattdessen wird kein NPE geworfen, denkt die AsyncTask, dass die Schaltfläche Referenz ist nicht null, setzt es sichtbar. Das Ergebnis? Nichts geschieht auf dem Bildschirm!

Update: Ich habe dies in Angriff genommen durch einen WeakReference auf die Aktivität zu halten und umzuschalten, wenn eine Konfigurationsänderung geschieht. 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 ändern Orientierung Ihre Telefone funktioniert.

War es hilfreich?

Lösung

AsyncTask nicht wiederverwendet werden entworfen, sobald eine Aktivität und neu gestartet zerrissen wurde. Das interne Handler Objekt ist veraltet, so wie du gesagt. In den Regalen Beispiel von Romain Guy, er einfach Annulliert läuft jeden derzeit AsyncTask die und startet dann wieder neue Post-Orientierung ändern.

Es ist möglich, aus Ihrem Thema bei der neuen Aktivität Hand, aber es fügt eine Menge von Sanitär. Es gibt keine allgemein auf Art und Weise vereinbart, dies zu tun, aber Sie können lesen über meine Methode hier: http://foo.jasonhudgins.com/2010/03/simple-progressbar-tutorial.html

Andere Tipps

Wenn Sie nur einen Rahmen brauchen, und werden es nicht verwenden für ui stopfen Sie einfach die Application zu Ihrem AsyncTask.You müssen den Kontext für Systemressourcen oft passieren können, zum Beispiel.

Versuchen Sie nicht, die Benutzeroberfläche von einem AsyncTask zu aktualisieren und versuchen Umgang Konfiguration zu vermeiden, ändert sich, wie es chaotisch zu bekommen. Um die Benutzeroberfläche bearbeiten Sie einen Rundfunkempfänger registrieren konnten und eine Übertragung senden.

Sie sollten auch die AsyncTask als separate öffentliche Klasse aus der Tätigkeit haben, wie oben erwähnt, macht es viel einfacher zu testen. Leider oft Android Programmierung verstärkt schlechte Praktiken und die offiziellen Beispiele helfen nicht.

Dies ist die Art von Dingen, die führen mich immer auf meine Aktivität zu verhindern, dass auf Orientierungsänderung zerstört / neu erstellt werden.

Das erreichen Sie, diese zu Ihrem <Activity> Tag in Ihrer Manifest-Datei:

android:configChanges="orientation|keyboardHidden" 

Und überschreibt onConfigurationChanged in Ihrer Aktivitätsklasse:

@Override
public void onConfigurationChanged(final Configuration newConfig)
{
    // Ignore orientation change to keep activity from restarting
    super.onConfigurationChanged(newConfig);
}

Um dies vermeiden Sie die Antwort givin hier benutzen: https://stackoverflow.com/a/2124731/327011

Wenn Sie jedoch die Aktivität (verschiedene Layouts für Hoch- und Querformat) zerstören Sie können die AsyncTask eine öffentliche Klasse machen (Lesen Sie hier, warum es nicht privat sein sollte Android: AsyncTask Empfehlungen: Private Klasse oder public class ) und dann ein Verfahren setActivity erstellen Sie den Verweis auf den Strom gesetzt Aktivität, wenn es zerstört wird / erstellt.

Sie können ein Beispiel siehe hier: Android AsyncTask in externen Klassen

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top