Android AsyncTask блокирует пользовательский интерфейс при изменении ориентации - PullRequest
1 голос
/ 09 марта 2011

У меня очень странная проблема. У меня есть AsyncTask, который блокирует поток пользовательского интерфейса при повороте телефона.

Во-первых, позвольте мне заявить, что мне комфортно, когда мои Activity уничтожаются и воссоздаются при вращении. Я сохраняю AsyncTask в onRetainNonConfigurationInstance(), отсоединяю от него Activity в onDestroy() и присоединяюсь к нему в onCreate(), используя getLastNonConfigurationInstance().

Все в порядке, пока AsyncTask не выполняет тяжелой работы. Например, для отладки моей проблемы, у меня есть это, и он работает точно так, как ожидалось, без блокировки пользовательского интерфейса:

@Override
protected Boolean doInBackground(Void... params) {
    boolean success = false;
    final DbAdapter dbAdapter = dbService.getAdapter();

    try {
        // pretend to do some complicated work
        Thread.sleep(20000);
        success = true;
    } catch (Exception e) {
        e.printStackTrace();
    }

    return success;
}

Однако, если я изменю его, чтобы выполнить некоторую фактическую работу в фоновом режиме, я получу очень большую задержку между вызовом onPause() для запуска вращения и вызовом onResume() позже в новой ориентации. Эта задержка составляет десятки секунд, в течение которых пользовательский интерфейс находится в несогласованном состоянии (старый макет обрезан в новой ориентации), и кажется, что вращение блокируется на AsyncTask. Единственное изменение - две строки внутри блока try:

@Override
protected Boolean doInBackground(Void... params) {
    boolean success = false;
    final DbAdapter dbAdapter = dbService.getAdapter();

    try {
        // actually do some complicated work
        XmlParser parser = new XmlParser(context, dbAdapter);
        success = parser.parse(source);
    } catch (Exception e) {
        e.printStackTrace();
    }

    return success;
}

context - это глобальный контекст приложения, передаваемый конструктору AsyncTask, поэтому я не думаю, что случайно сохранил ссылку на исходящий Activity.

Что еще может быть не так?

1 Ответ

1 голос
/ 09 марта 2011

Возможно, ваша деятельность также пытается использовать dbAdapter, и вы выполняете правильную синхронизацию, чтобы два потока не могли одновременно использовать dbAdapter.

Возможно, ваша деятельность пытается загрузить данные из файловой системы в главном потоке приложения, и ваши операции с базами данных вызывают слишком много конфликтов. На оборудовании YAFFS2 эффективно однопоточный для операций ввода-вывода.

Вы можете использовать Traceview, чтобы попытаться получить больше информации о том, что занимает ваше время, и вы можете использовать StrictMode на Android 2.2 и выше, чтобы увидеть, где ваша деятельность может пытаться выполнить файловый ввод / вывод на главном Тема приложения.

Кроме того, если ваш AsyncTask преобразует XML в записи базы данных, возможно, лучше использовать IntentService, чем AsyncTask.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...