Kể từ Android 17, các ứng dụng nhắm đến Android 17 (cấp độ API 37) trở lên sẽ nhận được một phương thức triển khai mới không khoá của android.os.MessageQueue. Cách triển khai mới giúp cải thiện hiệu suất và giảm số khung hình bị bỏ lỡ, nhưng có thể làm hỏng các ứng dụng khách phản ánh trên các trường và phương thức riêng tư của MessageQueue.
Android 17 giới thiệu một bản cải tiến đáng kể về cách hoạt động của Looper và Handler bằng cách viết lại lớp MessageQueue cơ bản.
Kể từ bản phát hành đầu tiên của hệ điều hành Android, MessageQueue đã dựa vào một khoá duy nhất để quản lý hàng đợi tác vụ của luồng chính. Thiết kế này thường gây ra tranh chấp khoá; luồng chính có thể bị chặn bởi một luồng trong nền, dẫn đến tình trạng rớt khung hình và giao diện người dùng bị giật.
Giảm thiểu tác động
Ứng dụng của bạn có thể chịu ảnh hưởng của thay đổi này nếu ứng dụng hoặc các phần phụ thuộc của ứng dụng dựa vào phản chiếu thời gian chạy để xem nhanh bên trong MessageQueue. Tránh sử dụng tính năng phản chiếu thời gian chạy để kiểm tra MessageQueue.
Với cách triển khai cũ, đôi khi nhà phát triển truy cập vào các trường riêng tư như MessageQueue.mMessages để kiểm tra thông báo đang chờ xử lý. Với cách triển khai không khoá mới, cấu trúc dữ liệu nội bộ đã thay đổi hoàn toàn.
Để duy trì khả năng tương thích nhị phân, Android 17 giữ lại trường mMessages, nhưng trong quá trình triển khai mới, trường này luôn rỗng, bất kể có thông báo trong hàng đợi hay không.
Ngoài ra, nếu sử dụng một số thư viện kiểm thử phổ biến, bạn cần cập nhật
thư viện của mình để tương thích với phương thức triển khai MessageQueue mới.
Espresso
Espresso thường được dùng để kiểm thử giao diện người dùng. Thư viện Espresso cần biết thời điểm luồng chính ở trạng thái rảnh để xác nhận chính xác trạng thái giao diện người dùng. Các phiên bản Espresso trước đây dựa vào kỹ thuật phản chiếu không còn tương thích với MessageQueue không khoá.
Hành động
Cập nhật lên Espresso 3.7.0 trở lên. Phiên bản này sử dụng API TestLooperManager, đặc biệt là các API mới mà Android 16 ra mắt, để tương tác an toàn với Looper mà không cần dựa vào thông tin triển khai nội bộ.
Robolectric
Tương tự, nếu chạy kiểm thử đơn vị bằng Robolectric, bạn có thể gặp vấn đề nếu các kiểm thử của bạn dựa vào chế độ Looper cũ.
Hành động
Cập nhật lên Robolectric 4.17 trở lên. Nếu đang sử dụng @LooperMode(LEGACY),
bạn sẽ cần di chuyển các thử nghiệm của mình sang @LooperMode(PAUSED) mới. Hãy tham khảo hướng dẫn di chuyển của Robolectric để biết thêm thông tin.
Kiểm thử hành vi
Bạn có thể kiểm thử ứng dụng của mình với thay đổi về hành vi trên Android 17 mà không cần cập nhật
targetSDK bằng cách thực thi lệnh sau:
adb am compat enable USE_NEW_MESSAGEQUEUE <your-package-name>
Lệnh này bật MessageQueue không khoá trong ứng dụng của bạn, nếu đó là một bản dựng có thể gỡ lỗi.
Nếu ứng dụng của bạn nhắm đến Android 17 (cấp độ API 37), thì hành vi mới sẽ được bật theo mặc định. Nếu nhận thấy hành vi không mong muốn hoặc sự cố sau khi nhắm đến cấp độ API này, bạn có thể tạm thời tắt phương thức triển khai mới để xác minh xem MessageQueue có phải là nguyên nhân hay không.
Bạn có thể bật/tắt thay đổi này bằng một trong hai cách sau:
Trình đơn Thay đổi về khả năng tương thích của ứng dụng trong Tùy chọn cho nhà phát triển.
Bằng cách chạy lệnh ADB sau:
adb am compat disable USE_NEW_MESSAGEQUEUE <your-package-name>
Thao tác này sẽ đưa ứng dụng của bạn về chế độ triển khai dựa trên khoá cũ, cho phép bạn xác định xem vấn đề có phải là do thay đổi hành vi của hàng đợi thông báo hay không.