هنگامی که بهینه سازی برنامه را با تنظیمات پیش فرض فعال می کنید ، R8 بهینه سازی های گسترده ای را انجام می دهد تا مزایای عملکرد شما را به حداکثر برساند. R8 تغییرات اساسی در کد ایجاد می کند، از جمله تغییر نام، جابجایی، و حذف فیلدها و روش های کلاس ها. اگر این باعث خطا می شود، باید مشخص کنید که کدام بخش از کد را با نوشتن قوانین حفظ کنید .
R8 ممکن است در شرایط زیر کد را به اشتباه حذف یا اصلاح کند:
- Reflection: کدی که با استفاده از بازتاب قابل دسترسی است، برای مثال با استفاده از
Class.forName()
یاMethod.invoke()
. R8 معمولاً نمی تواند تشخیص دهد که به کدام کلاس ها یا متدها از این طریق دسترسی خواهید داشت. - سریالسازی: کلاسها یا فیلدهای مورد نیاز برای سریالسازی و سریالزدایی ممکن است در R8 استفاده نشده باشند (این شکل دیگری از بازتاب است).
- رابط بومی جاوا (JNI): روش های جاوا که از کد بومی فراخوانی می شوند. R8 کد بومی را تجزیه و تحلیل نمی کند تا ببیند چه چیزی ممکن است به جاوا بازگردد.
این صفحه نحوه محدود کردن میزان بهینه سازی R8 را پوشش می دهد. برای آشنایی با نحوه سفارشی کردن منابع نگهداری شده، به افزودن قوانین حفظ منابع برای منابع رجوع کنید.
جایی که قوانین حفظ را اضافه کنیم
شما باید قوانین خود را به یک فایل proguard-rules.pro
که در دایرکتوری ریشه ماژول قرار دارد اضافه کنید (این فایل ممکن است قبلاً وجود داشته باشد، اما اگر نیست، آن را ایجاد کنید). برای اعمال قوانین موجود در فایل، باید فایل را در فایل build.gradle.kts
(یا build.gradle
) سطح ماژول خود، همانطور که در کد زیر نشان داده شده است، اعلام کنید:
کاتلین
android { buildTypes { release { isMinifyEnabled = true isShrinkResources = true proguardFiles( // Default file with default optimization rules. getDefaultProguardFile("proguard-android-optimize.txt"), // File with your custom rules. "proguard-rules.pro" ) ... } } ... }
شیار
android { buildTypes { release { minifyEnabled true shrinkResources true proguardFiles( // Default file with default optimization rules. getDefaultProguardFile('proguard-android-optimize.txt'), // File with your custom rules. 'proguard-rules.pro' ) ... } } // ... }
به طور پیش فرض، اسکریپت ساخت شما شامل فایل proguard-android-optimize.txt
نیز می شود. این فایل شامل قوانینی است که برای اکثر پروژه های اندروید مورد نیاز است، بنابراین باید آن را در اسکریپت ساخت نگه دارید.
نحوه نوشتن قوانین حفظ
در طول کامپایل برنامه، R8 با تجزیه و تحلیل نمودار تماس برنامه شما، که از ورودیهای مانیفست (مانند فعالیتها یا خدمات شما) شروع میشود و از طریق تماسهای تابع برنامه و کتابخانه ردیابی میشود، تشخیص میدهد که کدام کد باید در یک برنامه نگهداری شود. R8 کدهایی را حذف میکند که مستقیماً به این روش ارجاع داده نمیشوند، که اگر کد اجرا شده بخشی از این نمودار نباشد، میتواند باعث ایجاد مشکلاتی شود، برای مثال کدهایی که با بازتاب فراخوانی شدهاند. با نوشتن قوانین حفظ خود، میتوانید R8 را از کدهایی که باید در برنامه بماند مطلع کنید.
برای اضافه کردن یک قانون حفظ، یک خط -keep
در فایل proguard-rules.pro
اضافه کنید.
دستور قواعد را حفظ کنید
قوانین Keep معمولاً از این قالب پیروی می کنند:
-<KeepOption> [OptionalModifier,...] <ClassSpecification> [{ OptionalMemberSpecification }]
به عنوان مثال برای حفظ یک کلاس خاص و همه اعضای آن، از موارد زیر استفاده کنید:
-keep class com.myapp.MyClass { *; }
برای مثالهای بیشتر، بخش مثالها را ببینید.
این چیزی است که اجزای قانون نگه داشتن انجام می دهند:
<KeepOption>
به شما اجازه می دهد تا مشخص کنید چه جنبه هایی از یک کلاس حفظ شود:گزینه Keep توضیحات -نگه داشتن
کلاس و اعضای فهرست شده در
[{ OptionalMemberSpecification }]
را حفظ کنید.نگه داشتن اعضای کلاس
اجازه بهینه سازی کلاس. اگر کلاس حفظ شد، اعضای فهرست شده در
[{ OptionalMemberSpecification }]
را حفظ کنید.-نامها
اجازه حذف کلاس و اعضا را بدهید، اما به روشهای دیگر مبهم یا تغییر ندهید.
-keepclassmembernames
اجازه حذف کلاس و اعضا را بدهید، اما اعضا را به روشهای دیگر مبهم یا تغییر ندهید.
-کلاس ها را با اعضا نگه دارید
اگر اعضا با الگوی مشخص شده مطابقت داشته باشند، کلاس ها حذف یا مبهم نمی شوند.
توصیه میکنیم بیشتر از
-keepclassmembers
استفاده کنید، زیرا بیشترین بهینهسازیها را فعال میکند و در صورت نیاز-keepnames
استفاده کنید.-keep
اجازه هیچ گونه بهینه سازی را نمی دهد، بنابراین سعی کنید از آن کم استفاده کنید.[OptionalModifier],...]
به شما امکان می دهد صفر یا چند اصلاح کننده زبان جاوا را از یک کلاس فهرست کنید، به عنوان مثالpublic
یاfinal
.<ClassSpecification>
به شما این امکان را میدهد تا مشخص کنید که قانون keep روی کدام کلاس (یا کدام سوپرکلاس یا رابط پیادهسازی شده) اعمال شود. در ساده ترین حالت، این یک کلاس کاملاً واجد شرایط است.[{ OptionalMemberSpecification }]
به شما امکان میدهد رفتار نگهداری را فقط برای کلاسها و روشهایی که با الگوهای خاصی مطابقت دارند فیلتر کنید. به طور کلی این در اکثر قوانین نگهداری توصیه می شود تا از نگهداری بیش از حد مورد نظر جلوگیری شود.
نمونه های قوانین را حفظ کنید
در اینجا چند نمونه از قوانین حفظ خوب طراحی شده است.
ساخت زیر کلاس
این قانون نگه داشتن در داخل androidx.room:room-runtime
بسته بندی شده است تا سازنده های پایگاه داده را با بازتاب نمونه سازی کند.
-keep class * extends androidx.room.RoomDatabase { void <init>(); }
انعکاس از Android Framework ObjectAnimator
این قانون حفظ در داخل androidx.vectordrawable:vectordrawable-animated
بسته بندی شده است تا ObjectAnimator
قادر می سازد تا با JNI به دریافت کننده ها یا تنظیم کننده ها از کدهای بومی فراخوانی کند. توجه داشته باشید که سیستمهای انیمیشن جدیدتر در Compose نیازی به حفظ قوانینی مانند این ندارند، این فقط یک نمونه از ساختار قانون است.
-keepclassmembers class androidx.vectordrawable.graphics.drawable.VectorDrawableCompat$* {
void set*(***);
*** get*();
}
ثبت نام JNI
این قانون نگه داشتن در داخل androidx.graphics:graphics-path
بسته بندی شده است، که برای حفظ متدهای بومی استفاده می شود. اگر کتابخانه شما به صورت دستی متدهای بومی را با env->RegisterNatives()
ثبت کند، ممکن است لازم باشد.
-keepclasseswithmembers class androidx.graphics.path.** {
native <methods>;
}