Zachowanie kontekstu Android AsyncTask

Pracowałem z AsyncTasks w Androidzie i mam do czynienia z problemem.

Weźmy prosty przykład, działanie z jednym AsyncTask. Zadanie na tle nie robi nic spektakularnego, po prostu śpi przez 8 sekund.

Na końcu AsyncTask w metodzie onPostExecute () ustawiam status widoczności przycisku na View.VISIBLE, tylko po to, aby zweryfikować moje wyniki.

Teraz działa to świetnie, dopóki użytkownik nie zdecyduje się zmienić orientacji swoich telefonów podczas działania AsyncTask (w 8 sekundowym oknie uśpienia).

Rozumiem cykl życia aktywności Androida i wiem, że aktywność zostaje zniszczona i odtworzona.

W tym miejscu pojawia się problem. AsyncTask odnosi się do przycisku i najwyraźniej zawiera odniesienie do kontekstu, który rozpoczął AsyncTask.

Spodziewałbym się, że ten stary kontekst (ponieważ użytkownik spowodował zmianę orientacji) stał się zerowy, a AsyncTask rzucił NPE dla odniesienia do przycisku, który próbuje pokazać.

Zamiast tego nie jest generowany żaden NPE, AsyncTask uważa, że ​​odwołanie do przycisku nie ma wartości NULL, ustawia go na widoczny. Wynik? Nic się nie dzieje na ekranie!

Aktualizacja: Poradziłem sobie z tym, zachowującWeakReference do aktywności i przełączania, gdy nastąpi zmiana konfiguracji. To jest kłopotliwe.

Oto kod:

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

Spróbuj go wykonać i podczas pracy AsyncTask zmień orientację swoich telefonów.

questionAnswers(4)

yourAnswerToTheQuestion