راهنمای تغییر رفتار MessageQueue

با شروع از اندروید ۱۷، برنامه‌هایی که اندروید ۱۷ یا بالاتر را هدف قرار می‌دهند، پیاده‌سازی جدید و بدون قفل android.os.MessageQueue را دریافت می‌کنند. این پیاده‌سازی جدید عملکرد را بهبود می‌بخشد و فریم‌های از دست رفته را کاهش می‌دهد، اما ممکن است کلاینت‌هایی را که روی فیلدها و متدهای خصوصی MessageQueue تأمل می‌کنند، خراب کند.

اندروید ۱۷ با بازنویسی کلاس MessageQueue زیربنایی، بازنگری قابل توجهی در نحوه عملکرد Looper و Handler ارائه می‌دهد. از زمان اولین انتشار سیستم عامل اندروید، MessageQueue برای مدیریت صف وظایف نخ اصلی به یک قفل واحد متکی بود. این طراحی اغلب باعث ایجاد تداخل قفل می‌شد؛ نخ اصلی می‌توانست توسط یک نخ پس‌زمینه مسدود شود و منجر به افت فریم و اختلال در رابط کاربری شود.

کاهش تأثیر

اگر برنامه شما یا وابستگی‌های آن برای بررسی درون MessageQueue به بازتاب زمان اجرا (runtime reflection) متکی باشند، ممکن است تحت تأثیر این تغییر قرار گیرد. از استفاده از بازتاب زمان اجرا برای بررسی MessageQueue خودداری کنید.

با پیاده‌سازی قدیمی، توسعه‌دهندگان گاهی اوقات به فیلدهای خصوصی مانند MessageQueue.mMessages برای بررسی پیام‌های در انتظار دسترسی داشتند. با پیاده‌سازی جدید بدون قفل، ساختارهای داده داخلی کاملاً تغییر کرده‌اند. برای حفظ سازگاری دودویی، اندروید ۱۷ فیلد mMessages را نگه می‌دارد، اما در پیاده‌سازی جدید، این فیلد صرف نظر از اینکه آیا پیامی در صف وجود دارد یا خیر، همیشه تهی است.

علاوه بر این، اگر از برخی کتابخانه‌های تست محبوب استفاده می‌کنید، باید کتابخانه‌های خود را به‌روزرسانی کنید تا با پیاده‌سازی جدید MessageQueue سازگار باشند.

اسپرسو

Espresso معمولاً برای تست رابط کاربری استفاده می‌شود. کتابخانه Espresso باید بداند چه زمانی نخ اصلی بیکار است تا بتواند به درستی وضعیت رابط کاربری را ارزیابی کند. نسخه‌های اولیه Espresso به تکنیک‌های بازتاب متکی بودند که دیگر با MessageQueue بدون قفل سازگار نیستند.

اکشن

به Espresso 3.7.0 یا جدیدتر به‌روزرسانی کنید. این نسخه از API TestLooperManager ، به‌ویژه APIهای جدیدی که اندروید ۱۶ معرفی کرده است، برای تعامل ایمن با Looper بدون تکیه بر جزئیات پیاده‌سازی داخلی استفاده می‌کند.

روبولکتریک

به طور مشابه، اگر تست‌های واحد را با استفاده از Robolectric اجرا کنید، اگر تست‌های شما به حالت قدیمی Looper متکی باشند، ممکن است با مشکلاتی مواجه شوید.

اکشن

به Robolectric 4.17 یا جدیدتر به‌روزرسانی کنید. اگر از @LooperMode(LEGACY) استفاده می‌کنید، باید تست‌های خود را به @LooperMode(PAUSED) جدید منتقل کنید. برای اطلاعات بیشتر به راهنمای مهاجرت Robolectric مراجعه کنید.

رفتار را آزمایش کنید

شما می‌توانید برنامه خود را با تغییر رفتار در اندروید ۱۷ و بدون به‌روزرسانی targetSDK با اجرای دستور زیر آزمایش کنید:

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

این دستور، MessageQueue بدون قفل را در برنامه شما فعال می‌کند، البته اگر برنامه شما یک نسخه قابل اشکال‌زدایی باشد.

اگر برنامه شما اندروید ۱۷ را هدف قرار داده است، این رفتار جدید به طور پیش‌فرض فعال است. اگر پس از هدف قرار دادن این سطح API متوجه رفتار غیرمنتظره یا خرابی شدید، می‌توانید پیاده‌سازی جدید را موقتاً غیرفعال کنید تا بررسی کنید که آیا MessageQueue علت است یا خیر.

می‌توانید با استفاده از یکی از دو گزینه زیر، تغییر را فعال یا غیرفعال کنید:

  1. منوی تغییرات سازگاری برنامه در گزینه‌های توسعه‌دهنده .

  2. با اجرای دستور ADB زیر:

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

این کار برنامه شما را به پیاده‌سازی قدیمی و مبتنی بر قفل برمی‌گرداند و به شما امکان می‌دهد تشخیص دهید که آیا مشکل ناشی از تغییر رفتار صف پیام بوده است یا خیر.