Я работаю с AsyncTasks в Android, и я имею дело с проблемой.
Возьмем простой пример: активность с одной 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 изменит ориентацию вашего телефона.