Panduan perubahan perilaku MessageQueue

Mulai Android 17, aplikasi yang menargetkan Android 17 atau yang lebih tinggi menerima penerapan bebas kunci baru dari android.os.MessageQueue. Implementasi baru ini meningkatkan performa dan mengurangi frame yang terlewat, tetapi dapat merusak klien yang mencerminkan kolom dan metode pribadi MessageQueue.

Android 17 memperkenalkan perombakan signifikan pada cara kerja Looper dan Handler, dengan menulis ulang class MessageQueue yang mendasarinya. Sejak rilis pertama sistem operasi Android, MessageQueue mengandalkan satu kunci untuk mengelola antrean tugas thread utama. Desain ini sering kali menyebabkan pertentangan kunci; thread utama dapat diblokir oleh thread latar belakang, yang menyebabkan frame terputus dan jank UI.

Memitigasi dampak

Aplikasi Anda mungkin terpengaruh oleh perubahan ini jika aplikasi atau dependensinya mengandalkan refleksi runtime untuk melihat ke dalam MessageQueue. Hindari penggunaan refleksi runtime untuk memeriksa MessageQueue.

Dengan penerapan lama, developer terkadang mengakses kolom pribadi seperti MessageQueue.mMessages untuk memeriksa pesan yang tertunda. Dengan implementasi bebas kunci yang baru, struktur data internal telah berubah sepenuhnya. Untuk mempertahankan kompatibilitas biner, Android 17 mempertahankan kolom mMessages, tetapi dalam implementasi baru, kolom ini selalu null, terlepas dari apakah ada pesan dalam antrean atau tidak.

Selain itu, jika Anda menggunakan beberapa library pengujian populer, Anda harus mengupdate library agar kompatibel dengan penerapan MessageQueue baru.

Espresso

Espresso biasanya digunakan untuk pengujian UI. Pustaka Espresso perlu mengetahui kapan thread utama tidak ada aktivitas untuk menegaskan status UI dengan benar. Versi Espresso sebelumnya mengandalkan teknik refleksi yang tidak lagi kompatibel dengan MessageQueue bebas kunci.

Tindakan

Update ke Espresso 3.7.0 atau yang lebih baru. Versi ini menggunakan API TestLooperManager, khususnya API baru yang diperkenalkan Android 16, untuk berinteraksi dengan Looper secara aman tanpa mengandalkan detail implementasi internal.

Robolectric

Demikian pula, jika Anda menjalankan pengujian unit menggunakan Robolectric, Anda mungkin mengalami masalah jika pengujian Anda mengandalkan mode Looper lama.

Tindakan

Update ke Robolectric 4.17 atau yang lebih baru. Jika Anda menggunakan @LooperMode(LEGACY), Anda harus memigrasikan pengujian ke @LooperMode(PAUSED) baru. Lihat panduan migrasi Robolectric untuk mengetahui informasi selengkapnya.

Menguji perilaku

Anda dapat menguji aplikasi dengan perubahan perilaku di Android 17 tanpa mengupdate targetSDK dengan menjalankan perintah berikut:

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

Perintah ini mengaktifkan MessageQueue bebas kunci di aplikasi Anda, jika aplikasi tersebut adalah build yang dapat di-debug.

Jika aplikasi Anda menargetkan Android 17, perilaku baru diaktifkan secara default. Jika Anda melihat perilaku atau error yang tidak terduga setelah menargetkan level API ini, Anda dapat menonaktifkan penerapan baru untuk sementara guna memverifikasi apakah MessageQueue adalah penyebabnya.

Anda dapat mengalihkan perubahan menggunakan salah satu dari dua opsi:

  1. Menu Perubahan Kompatibilitas Aplikasi di Opsi Developer.

  2. Dengan menjalankan perintah ADB berikut:

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

Tindakan ini akan mengembalikan aplikasi Anda ke implementasi berbasis kunci lama, sehingga Anda dapat mengidentifikasi apakah masalah tersebut disebabkan oleh perubahan perilaku antrean pesan.