بهینه‌سازی‌ها را به‌صورت افزایشی اتخاذ کنید

به‌طور پیش‌فرض، R8 بهینه‌سازی‌های زیادی برای بهبود عملکرد و اندازه انجام می‌دهد، اما ممکن است این بهینه‌سازی‌ها فوراً برای برنامه شما کار نکنند. اگر برای اولین‌بار R8 را در برنامه بزرگی روشن می‌کنید (یا حالت کامل را فعال می‌کنید)، سعی کنید بهینه‌سازی‌ها را به‌صورت افزایشی اتخاذ کنید: به‌طور موقت مبهم‌سازی را خاموش کنید و R8 را برای بخش‌هایی از کد به‌طور هم‌زمان فعال کنید، نه برای همه کد در برنامه‌تان. توصیه می‌کنیم این رویکرد افزایشی را درطول توسعه محلی اتخاذ کنید، اما می‌توانید از آن درطول آزمایش تضمین کیفیت داخلی یا حتی در تولید به‌عنوان عرضه تدریجی استفاده کنید. مراحل دقیقی که انجام می‌دهید به خط زمان موردنظر شما و اطمینان شما از پوشش آزمایش پیش‌انتشار بستگی دارد.

بهینه‌سازی‌ها را محدود کنید

‫R8 انواع مختلفی از بهینه‌سازی‌ها را انجام می‌دهد، ازجمله برداشتن کد، بازنویسی کد، و برداشتن منابع. در اینجا چند شرح سطح بالا از انواع بهینه‌سازی آورده شده است:

  • کوچک کردن کد (یا تکاندن درخت): کد بدون ارجاع را برمی‌دارد
  • مبهم‌سازی (یا کوچک‌سازی شناسه): نام کلاس‌ها و روش‌ها را کوتاه می‌کند
  • بهینه‌سازی: کد را بازنویسی می‌کند، برای مثال درون‌خطی‌سازی

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

فقط فعال کردن حذف کدهای بلااستفاده

کوچک کردن کد، که به‌عنوان تکاندن درخت هم شناخته می‌شود، کدهایی را که به‌نظر می‌رسد بدون ارجاع باشند برمی‌دارد. توصیه می‌کنیم فقط با «حذف کد بلااستفاده» شروع کنید، زیرا این روش ساده‌ترین روش است.

برای فعال کردن فقط «درخت‌تکانی»، موارد زیر را به فایل proguard-rules.pro اضافه کنید تا انواع دیگر بهینه‌سازی‌ها را غیرفعال کنید. خاموش کردن مبهم‌سازی کلیدی است زیرا باعث می‌شود خواندن ردیابی پشته بسیار آسان‌تر شود.

-dontobfuscate // Use temporarily to turn off identifier minification
-dontoptimize // Use temporarily to turn off optimization

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

استفاده از حالت سازگاری

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

برای استفاده از حالت سازگاری، از تنظیم زیر در فایل gradle.properties استفاده کنید:

android.enableR8.fullMode = false // Use temporarily to disable full mode

فعال کردن بقیه بهینه‌سازی‌ها

وقتی مطمئن شدید که «حذف کد غیرقابل‌دسترس» برای برنامه‌تان کار می‌کند، می‌توانید تنظیمات قبلی را بردارید تا مبهم‌سازی، بهینه‌سازی، و حالت کامل R8 دوباره فعال شود. توجه داشته باشید که مبهم‌سازی می‌تواند اشکال‌زدایی را دشوارتر کند، به همین دلیل است که توصیه می‌کنیم ابتدا مشکلات حذف کد بلااستفاده را برطرف کنید.

برای اطلاعات بیشتر درباره ابهام‌زدایی ردیابی پشته‌ای، به بازیابی ردیابی پشته‌ای اصلی مراجعه کنید.

محدود کردن دامنه بهینه‌سازی

ساخت کاملاً بهینه‌شده همه کدها را در هر کتابخانه و بسته بهینه‌سازی می‌کند، بنابراین رایج است که هنگام اولین روشن کردن R8 با مشکلاتی مواجه شوید. اگر در بخشی از برنامه با مشکلی در بهینه‌سازی مواجه شدید، R8 را به‌طور کامل خاموش نکنید، وگرنه مزایای آن را در جاهای دیگر ازدست خواهید داد. درعوض، R8 را فقط در بخش‌هایی از برنامه‌تان که باعث مشکل می‌شود موقتاً غیرفعال کنید.

استفاده از قوانین نگهداری در سطح بسته

توصیه می‌کنیم از قوانین نگهداری در سطح بسته به‌عنوان راهی برای غیرفعال کردن موقت R8 در بخش‌هایی از برنامه‌تان استفاده کنید. همیشه باید بعداً برای رفع این مشکلات بهینه‌سازی برگردید؛ این معمولاً یک راه‌حل موقت برای دور زدن مناطق مشکل‌دار است.

برای مثال، اگر بخشی از برنامه‌تان به‌شدت از Gson استفاده می‌کند و باعث ایجاد مشکل در بهینه‌سازی می‌شود، راه‌حل ایده‌آل این است که قوانین نگهداری هدفمند بیشتری اضافه کنید یا به راه‌حل codegen بروید. اما برای رفع انسداد بهینه‌سازی بقیه برنامه، می‌توانید کد تعریف‌کننده انواع Gson را در یک زیربسته اختصاصی قرار دهید و قانونی مانند این را به فایل proguard-rules.pro خود اضافه کنید:

-keep class com.myapp.json.** { *; }

اگر کتابخانه‌ای که استفاده می‌کنید دارای بازتاب در مؤلفه‌های داخلی است، می‌توانید به‌طور مشابه یک قانون حفظ برای کل کتابخانه اضافه کنید. باید کد کتابخانه یا JAR/AAR را بررسی کنید تا بسته مناسب را برای نگهداری پیدا کنید. باز هم می‌گوییم که این کار برای حفظ طولانی‌مدت توصیه نمی‌شود، اما می‌تواند بهینه‌سازی بقیه برنامه را لغو انسداد کند:

-keep class com.somelibrary.** { *; }

برداشتن قوانین نگهداری در سطح بسته

وقتی برنامه‌تان با قوانین نگهداری در سطح بسته به‌درستی کار کرد، باید برگردید و یا قوانین نگهداری هدفمند اضافه کنید یا استفاده از بازتاب یا کتابخانه‌ای را که در وهله اول قانون نگهداری را ضروری می‌کند بردارید.

برای مثال، نگه داشتن همه قوانینی که کلاس خاصی را گسترش می‌دهند در AndroidX بسیار رایج است تا فقط کلاس‌های مرتبط نگه داشته شوند. به‌طور کلی، بازتاب فقط باید کلاس‌ها یا روش‌هایی را هدف قرار دهد که یا کلاس‌های انتزاعی خاصی را گسترش می‌دهند، میاناهای خاصی را پیاده‌سازی می‌کنند، یا به کلاس‌هایی با حاشیه‌نویسی زمان اجرای خاصی تبدیل می‌شوند. هرکدام از این‌ها روش‌های پشتیبانی‌شده‌ای برای تعریف قوانین نگهداری هستند تا در برنامه نهایی و کاملاً بهینه‌شده‌تان به قوانین نگهداری در سطح بسته نیاز نداشته باشید.

اگر بازتاب در پایگاه کد خودتان وجود دارد، می‌توانید قوانین نگهداری در سطح بسته را با Jetpack Keep جایگزین کنید. قوانین تولیدشده شرطی هستند: R8 هدف تماس بازتابی را فقط درصورتی نگه می‌دارد که کدی را که تماس را برقرار می‌کند نیز نگه دارد. برای انتقال بسته، از بررسی‌های Jetpack Keep lint برای یافتن و حاشیه‌نویسی کردن فراخوانی‌های بازتابی آن استفاده کنید، و سپس قانون سراسری بسته را بردارید.