Я работал с AsyncTasks в Android, и я занимаюсь проблемой.
Возьмите простой пример, Действие с одним AsyncTask. Задача на фоне не делает ничего захватывающего, это просто спит в течение 8 секунд.
В конце AsyncTask в onPostExecute () метод я просто устанавливаю состояние видимости кнопки для Просмотра. ВИДИМЫЙ, только для проверки моих результатов.
Теперь, это работает отлично, пока пользователь не решает изменить свою ориентацию телефонов, в то время как AsyncTask работает (в 8 вторых окнах сна).
Я понимаю жизненный цикл действия Android, и я знаю, что действие уничтожается и воссоздало.
Это - то, где проблема входит. AsyncTask обращается к кнопке и по-видимому содержит ссылку на контекст, который запустил AsyncTask во-первых.
Я ожидал бы, что этот старый контекст (так как пользователь вызвал изменение ориентации) к любому становится пустым и AsyncTask для броска NPE для ссылки на кнопку, которую это пытается сделать видимым.
Вместо этого никакой NPE не брошен, AsyncTask думает, что ссылка кнопки не является нулевой, наборы он к видимому. Результат? Ничего не происходит на экране!
Обновление: Я занялся этим путем хранения a 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 работает, изменяют Вашу ориентацию телефонов.
AsyncTask не предназначен для повторного использования после разрыва и перезапуска Activity. Внутренний объект Handler становится устаревшим, как вы и заявили. В примере с полками Ромена Гая он просто отменяет все запущенные в данный момент AsyncTask, а затем перезапускает новые после изменения ориентации.
Вы можете передать свою тему новому действию, но это добавит много дополнительных элементов. Не существует общепринятого способа сделать это, но вы можете прочитать о моем методе здесь: http://foo.jasonhudgins.com/2010/03/simple-progressbar-tutorial.html
Это тот тип вещей, который заставляет меня всегда препятствовать уничтожению/восстановлению моей Деятельности при смене ориентации.
Для этого добавьте это к вашему тегу
в файле манифеста:
android:configChanges="orientation|keyboardHidden"
И переопределите onConfigurationChanged в вашем классе Activity:
@Override
public void onConfigurationChanged(final Configuration newConfig)
{
// Ignore orientation change to keep activity from restarting
super.onConfigurationChanged(newConfig);
}