هنگام کار با قوانین Keep، رسیدن به میزان مناسبی از جزئیات (specification) مهم است تا مطمئن شوید که ضمن حفظ رفتار برنامه، مزایایی را مشاهده میکنید. برای آشنایی با الگوهای خوب و همچنین مواردی که باید در قوانین Keep از آنها اجتناب کنید، به بخشهای زیر مراجعه کنید.
الگوهای خوب در قوانین حفظ
قوانین نگهداری که به خوبی تعریف شدهاند، تا حد امکان خاص هستند و از الگوهای زیر پیروی میکنند:
برای مشخصات کلاس، در صورت امکان، همیشه یک کلاس خاص، کلاس پایه یا کلاس حاشیهنویسی شده را مشخص کنید، همانطور که در مثالهای زیر نشان داده شده است:
-keepclassmembers class com.example.MyClass { void someSpecificMethod(); }-keepclassmembers ** extends com.example.MyBaseClass { void someSpecificMethod(); }-keepclassmembers @com.example.MyAnnotation class ** { void someSpecificMethod(); }هر زمان که ممکن بود، از حاشیهنویسیها روی کد منبع خود استفاده کنید و سپس آن حاشیهنویسیها را مستقیماً در قوانین keep خود هدف قرار دهید. این کار یک پیوند واضح و روشن بین کد شما و قوانینی که آن را حفظ میکنند ایجاد میکند و پیکربندی شما را قویتر، قابل فهمتر و کمتر مستعد خرابی هنگام تغییر کد میکند.
برای مثال، قطعه کد زیر نشان میدهد که چگونه میتوانید کلاس MyClass و همچنین کلاسهای دیگری را که با
@com.example.DisplayComponentحاشیهنویسی شدهاند، حفظ کنید:// In the source code @com.example.DisplayComponent class MyClass { /* ... */ } // In the keep rules -keep @com.example.DisplayComponent class * {*;}توصیه میکنیم حاشیهنویسیهای خود را طوری نامگذاری کنید که زمینه معناداری برای دلیل حفظ بخشهای کد ارائه دهند. برای مثال، برای برنامهای که اجزای نمایش آن نیاز به حفظ برخی از بخشها دارند، از
@DisplayComponentاستفاده کنید.هر زمان که ممکن باشد، مشخصات عضو باید اعلان شود و فقط به بخشهایی از کلاس که باید برای عملکرد برنامه نگه داشته شوند، اشاره کند. توصیه میشود با تعریف محدوده عضو اختیاری به صورت
{ *; }، مگر اینکه کاملاً ضروری باشد، یک قانون را بر کل کلاس اعمال نکنید.-keepclassmembers com.example.MyClass { void someSpecificMethod(); void @com.example.MyAnnotation *; }اگر از گزینه سراسری
repackageclassesاستفاده میکنید، از مشخص کردن نام بسته اختیاری خودداری کنید. این کار منجر به فایلهای DEX کوچکتر میشود زیرا پیشوند بسته در نام کلاسهای repackage شده حذف میشود.قوانین keep را برای تمام مواردی که توسط reflection قابل دسترسی هستند، حفظ کنید. حتی اگر چنین مواردی توسط R8 بدون قوانین صریح keep حفظ شوند، حفظ قوانین واقعی بسیار مهم است زیرا تغییرات کد در آینده میتواند منجر به این شود که R8 دیگر این موارد را حفظ نکند.
اگر نمیتوانید از این دستورالعملها پیروی کنید، میتوانید کدی را که باید در یک بسته اختصاصی نگهداری شود، موقتاً جدا کنید و قانون keep خود را روی بسته اعمال کنید. با این حال، این یک راه حل برای درازمدت نیست. برای کسب اطلاعات بیشتر، به بخش «بهینهسازیهای تدریجی را اتخاذ کنید» مراجعه کنید. برای استفاده از قانون keep برای یک بسته، یک قانون keep را همانطور که در مثال زیر نشان داده شده است، تعریف کنید:
-keepclassmembers class com.example.pkg.** { *; }
مواردی که باید از آنها اجتناب کرد
سینتکس قانون keep گزینههای زیادی دارد، اما برای مزایای عملکرد پایدار و قابل اندازهگیری، توصیه میکنیم از موارد زیر استفاده نکنید:
- از قوانین keep در سطح بسته مانند
-keep class com.example.pkg.** { *; }برای مدت طولانی استفاده نکنید. آنها میتوانند به طور موقت برای حل مشکلات هنگام پیکربندی R8 استفاده شوند. برای اطلاعات بیشتر، به بخش محدود کردن دامنه بهینهسازی مراجعه کنید. به طور کلی، در مورد wildcardها مراقب باشید - مطمئن شوید که فقط کدی را که نیاز دارید نگه میدارید. - در صورت امکان، از کتابخانههایی که هنگام استفاده از قوانین keep، به شما پیشنهاد کپی و پیست کردن میدهند، به خصوص قوانین keep در کل پکیج، خودداری کنید. کتابخانههایی که برای عملکرد خوب در اندروید طراحی شدهاند، باید در صورت امکان از انعکاس (reflection) اجتناب کنند و در صورت لزوم، قوانین keep مصرفکننده را در خود جایگذاری کنند .
- از استفاده از عملگر وارونگی
!در قوانین keep خودداری کنید، زیرا ممکن است ناخواسته یک قانون را تقریباً به هر کلاسی در برنامه خود اعمال کنید.
اگر نمیتوانید از این قوانین پیروی کنید، ممکن است از بازتابهای باز زیادی استفاده کنید و باید یا از بازتاب اجتناب کنید یا از کتابخانهای که از بازتاب استفاده میکند، اجتناب کنید (به مطالعه موردی Gson مراجعه کنید).