Поведение Android AsyncTask контекста

Я работал с 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 работает, изменяют Вашу ориентацию телефонов.

33
задан dnkoutso 21 August 2013 в 14:39
поделиться

2 ответа

AsyncTask не предназначен для повторного использования после разрыва и перезапуска Activity. Внутренний объект Handler становится устаревшим, как вы и заявили. В примере с полками Ромена Гая он просто отменяет все запущенные в данный момент AsyncTask, а затем перезапускает новые после изменения ориентации.

Вы можете передать свою тему новому действию, но это добавит много дополнительных элементов. Не существует общепринятого способа сделать это, но вы можете прочитать о моем методе здесь: http://foo.jasonhudgins.com/2010/03/simple-progressbar-tutorial.html

23
ответ дан 27 November 2019 в 19:30
поделиться

Это тот тип вещей, который заставляет меня всегда препятствовать уничтожению/восстановлению моей Деятельности при смене ориентации.

Для этого добавьте это к вашему тегу в файле манифеста:

android:configChanges="orientation|keyboardHidden" 

И переопределите onConfigurationChanged в вашем классе Activity:

@Override
public void onConfigurationChanged(final Configuration newConfig)
{
    // Ignore orientation change to keep activity from restarting
    super.onConfigurationChanged(newConfig);
}
2
ответ дан 27 November 2019 в 19:30
поделиться
Другие вопросы по тегам:

Похожие вопросы: