Я работаю с AsyncTasks в Android и имею дело с проблемой.
Возьмите простой пример, Activity с одним AsyncTask. Задание на заднем плане не делает ничего впечатляющего, оно просто спит 8 секунд.
В конце AsyncTask в методе onPostExecute () я просто устанавливаю статус видимости кнопки в View.VISIBLE, только для проверки моих результатов.
Теперь это прекрасно работает, пока пользователь не решит изменить ориентацию своих телефонов во время работы AsyncTask (в пределах 8-секундного окна ожидания).
Я понимаю жизненный цикл активности Android и знаю, что активность уничтожается и воссоздается.
Вот тут и возникает проблема. AsyncTask ссылается на кнопку и, очевидно, содержит ссылку на контекст, который первым запустил AsyncTask.
Я ожидаю, что этот старый контекст (поскольку пользователь вызвал изменение ориентации) либо станет нулевым, либо AsyncTask сгенерирует NPE для ссылки на кнопку, которую он пытается сделать видимой.
Вместо этого NPE не выбрасывается, AsyncTask считает, что ссылка на кнопку не является нулевой, устанавливает его в видимый. Результат? На экране ничего не происходит!
Обновление: Я решил эту проблему, оставив WeakReference
для активности и переключаясь при изменении конфигурации. Это громоздко.
Вот код:
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);
}
}
}
Попробуйте выполнить его, и пока AsyncTask работает, измените ориентацию вашего телефона.