Начиная с Android 17, приложения, предназначенные для Android 17 (уровень API 37) или более поздней версии, получают новую реализацию android.os.MessageQueue без блокировки. Новая реализация повышает производительность и уменьшает количество пропущенных кадров, но может нарушить работу клиентов, которые используют закрытые поля и методы MessageQueue.
В Android 17 значительно переработаны принципы работы Looper и Handler. Это связано с изменением базового класса MessageQueue.
С момента выпуска первой версии операционной системы Android в MessageQueue использовалась одна блокировка для управления очередью задач основного потока. Такой подход часто приводил к конфликтам блокировок: основной поток мог быть заблокирован фоновым, что вызывало пропуск кадров и задержки в интерфейсе.
Смягчение последствий
Это изменение может повлиять на ваше приложение, если оно или его зависимости используют рефлексию во время выполнения для заглядывания внутрь MessageQueue. Не используйте рефлексию во время выполнения для проверки MessageQueue.
При использовании устаревшей реализации разработчики иногда обращались к закрытым полям, таким как MessageQueue.mMessages, чтобы проверить ожидающие сообщения. В новой реализации без блокировок внутренние структуры данных полностью изменились.
Чтобы сохранить двоичную совместимость, в Android 17 поле mMessages сохранено, но в новой реализации оно всегда имеет значение null, независимо от того, есть ли сообщения в очереди.
Кроме того, если вы используете популярные библиотеки для тестирования, вам нужно будет обновить их, чтобы они были совместимы с новой реализацией MessageQueue.
Espresso
Espresso обычно используется для тестирования пользовательского интерфейса. Библиотеке Espresso необходимо знать, когда основной поток бездействует, чтобы правильно подтвердить состояние пользовательского интерфейса. Предыдущие версии Espresso полагались на методы отражения, которые больше не совместимы с MessageQueue без блокировки.
Действие
Обновите Espresso до версии 3.7.0 или более поздней. В этой версии используется API TestLooperManager, в частности новые API, представленные в Android 16, для безопасного взаимодействия с Looper без необходимости полагаться на внутренние детали реализации.
Robolectric
Аналогично, если вы запускаете модульное тестирование с помощью 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 37), новое поведение включено по умолчанию. Если после перехода на этот уровень API вы заметите сбои или другие проблемы, то можете временно отключить новую реализацию, чтобы проверить, не связана ли она с MessageQueue.
Вы можете включить или отключить изменение двумя способами:
Меню Изменения совместимости приложений в разделе Для разработчиков.
Выполните следующую команду ADB:
adb am compat disable USE_NEW_MESSAGEQUEUE <your-package-name>
Это позволит вам вернуться к устаревшей реализации на основе блокировки и определить, была ли проблема вызвана изменением поведения очереди сообщений.