Рекомендации по изменению поведения очередей сообщений

Начиная с Android 17, приложения, ориентированные на Android 17 и выше, получают новую реализацию android.os.MessageQueue без блокировок. Новая реализация повышает производительность и уменьшает количество пропущенных кадров, но может привести к сбоям в работе клиентов, использующих закрытые поля и методы MessageQueue .

В Android 17 существенно переработана работа Looper и Handler за счет переписывания базового класса MessageQueue . С момента первого выпуска операционной системы Android класс MessageQueue полагался на единственную блокировку для управления очередью задач основного потока. Такая конструкция часто приводила к конфликтам блокировок; основной поток мог быть заблокирован фоновым потоком, что приводило к потере кадров и зависанию пользовательского интерфейса.

Смягчить последствия

Это изменение может повлиять на ваше приложение, если оно или его зависимости используют рефлексию во время выполнения для просмотра содержимого MessageQueue . Избегайте использования рефлексии во время выполнения для проверки MessageQueue .

В старой реализации разработчики иногда обращались к закрытым полям, таким как MessageQueue.mMessages , для проверки ожидающих сообщений. В новой реализации без блокировок внутренние структуры данных полностью изменились. Для сохранения бинарной совместимости Android 17 сохраняет поле mMessages , но в новой реализации это поле всегда равно null , независимо от того, есть ли сообщения в очереди.

Кроме того, если вы используете популярные библиотеки для тестирования, вам потребуется обновить их, чтобы они были совместимы с новой реализацией MessageQueue .

Эспрессо

Espresso широко используется для тестирования пользовательского интерфейса. Библиотеке Espresso необходимо знать, когда основной поток находится в режиме ожидания, чтобы корректно проверять состояние пользовательского интерфейса. Более ранние версии Espresso использовали методы рефлексии, которые больше не совместимы с MessageQueue, не использующим блокировки.

Действие

Обновите Espresso до версии 3.7.0 или новее. Эта версия использует API TestLooperManager , в частности, новые API, представленные в Android 16, для безопасного взаимодействия с Looper без зависимости от внутренних особенностей реализации.

Робоэлектрик

Аналогично, при запуске модульных тестов с использованием Robolectric могут возникнуть проблемы, если ваши тесты используют устаревший режим Looper.

Действие

Обновите Robolectric до версии 4.17 или новее. Если вы используете @LooperMode(LEGACY) , вам потребуется перевести ваши тесты на новый @LooperMode(PAUSED) . Для получения дополнительной информации обратитесь к руководству по миграции Robolectric .

Проверьте поведение

Вы можете протестировать свое приложение с измененным поведением на Android 17 без обновления targetSDK , выполнив следующую команду:

adb am compat enable USE_NEW_MESSAGEQUEUE <your-package-name>

Эта команда включает в ваше приложение MessageQueue без блокировок, если это отлаживаемая сборка.

Если ваше приложение ориентировано на Android 17, новое поведение включено по умолчанию. Если вы заметите неожиданное поведение или сбои после перехода на этот уровень API, вы можете временно отключить новую реализацию, чтобы проверить, не является ли причиной проблема MessageQueue .

Вы можете включить или выключить это изменение, используя один из двух вариантов:

  1. Меню «Изменения совместимости приложения» находится в разделе «Параметры разработчика» .

  2. Выполнив следующую команду ADB:

    adb am compat disable USE_NEW_MESSAGEQUEUE <your-package-name>
    

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