Bắt đầu từ Android 17, các ứng dụng nhắm đến Android 17 trở lên sẽ nhận được một cách triển khai mới không có khoá của android.os.MessageQueue. Việc triển khai mới này 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 những ứng dụng phản ánh các trường và phương thức riêng tư MessageQueue.
Android 17 giới thiệu một bản đại tu đá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ừ lầ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 tình trạng 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 giảm số 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 xét 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 việc 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 các thông báo đang chờ xử lý. Với việc 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 vẫn giữ trường mMessages, nhưng trong quy trình triển khai mới, trường này luôn có giá trị rỗng, bất kể có thông báo nà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 sẽ cần cập nhật các thư viện của mình để tương thích với chế độ 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 đúng trạng thái giao diện người dùng. Các phiên bản cũ của Espresso dựa vào các kỹ thuật phản chiếu không còn tương thích với MessageQueue không khoá nữa.
Thao tác
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 đã giới thiệu, để tương tác an toàn với Looper mà không cần dựa vào thông tin chi tiết về việc 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 phải vấn đề nếu các kiểm thử của bạn dựa vào chế độ Looper cũ.
Thao tác
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 kiểm thử 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 cho phép MessageQueue không khoá trong ứng dụng của bạn, nếu đó là bản dựng có thể gỡ lỗi.
Nếu ứng dụng của bạn nhắm đến Android 17, thì theo mặc định, hành vi mới sẽ được bật. 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 chế độ 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 bằng một trong hai cách sau:
Trình đơn Các thay đổi về khả năng tương thích của ứng dụng trong Tuỳ 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ẽ khôi phục ứng dụng của bạn về phương thức 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 về hành vi của hàng đợi tin nhắn hay không.