عند تفعيل تحسين التطبيق، يختلف السلوك التلقائي لأداة التحسين باختلاف إصدارات R8.
- باستخدام لغة DSL المعدَّلة المتوفّرة في الإصدار 9.3 من "مكوّن Android Gradle" والإصدارات الأحدث، يتم تفعيل تقليص الموارد تلقائيًا عند تفعيل التحسين. يُرجى العِلم أنّه لا يزال يتم دعم لغة DSL القديمة التي تتطلّب تفعيل تحسين الرموز والموارد بشكلٍ منفصل.
بالنسبة إلى الإصدارات التي تسبق الإصدار 9.3 من "مكوّن Android Gradle"، يطلب الإعداد
isShrinkResources = trueمن أداة التحسين إزالة الموارد غير المستخدَمة، ما يساعد في تقليل حجم تطبيقك. لا يعمل تقليص الموارد إلا بالتزامن مع تقليص الرموز، لذا إذا كنت بصدد تحسين الموارد، اضبط أيضًاisMinifyEnabled = true.
الإصدار 9.3 من "مكوّن Android Gradle" والإصدارات الأحدث (Kotlin)
buildTypes {
release {
optimization {
enable = true // Enables code and resource optimizations.
}
}
}
الإصدار 9.3 من "مكوّن Android Gradle" والإصدارات الأحدث (Groovy)
buildTypes {
release {
optimization {
enable = true // Enables code and resource optimizations.
}
}
}
لغة DSL القديمة (Kotlin)
buildTypes {
release {
isMinifyEnabled = true
isShrinkResources = true
...
}
}
لغة DSL القديمة (Groovy)
buildTypes {
release {
minifyEnabled = true
shrinkResources = true
...
}
}
إذا أردت الاحتفاظ بموارد معيّنة أو تجاهلها، أنشئ ملف XML keep في موارد مشروعك، مثلاً res/raw/my.package.keep.xml. يحتوي ملف keep على المكوّنات التالية:
- العلامة
<resources>— تحتوي على جميع عناصر الموارد الثانوية و سمات الاحتفاظ/التجاهل. - السمة
tools:keep: تقبل قائمة قيم مفصولة بفاصلة بأسماء الموارد التي تحدّد الموارد التي يجب الاحتفاظ بها - السمة
tools:discard: تقبل قائمة قيم مفصولة بفاصلة بأسماء الموارد التي تحدّد الموارد التي يجب تجاهلها
استخدِم علامة النجمة كحرف بدل للإشارة إلى موارد متعددة في المجلد نفسه، مثلاً:
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools"
tools:keep="@layout/l_used*_c,@layout/l_used_a,@layout/l_used_b*"
tools:discard="@layout/unused2" />
قد يبدو تحديد الموارد التي يجب تجاهلها أمرًا غير ضروري في حين يمكنك بدلاً من ذلك حذفها، ولكن قد يكون تجاهل الموارد مفيدًا عند استخدام تنويعات الإنشاء.
استهداف تنويعات إنشاء معيّنة
لإزالة الموارد في بعض تنويعات التصميم فقط، ضَع جميع مواردك في دليل المشروع الشائع، ثم أنشئ ملفًا مختلفًا باسم my.package.build.variant.keep.xml لكل تنويعة تصميم في دليل موارد التنويعة. في ملف keep، حدِّد يدويًا الموارد التي يجب إزالتها عندما يبدو أنّ أحد الموارد مستخدَم في الرمز (وبالتالي لا تتم إزالته بواسطة أداة تقليص الحجم)، ولكنك تعلم أنّه لن يتم استخدامه فعليًا لتنويعة التصميم المحدّدة.
إزالة الموارد البديلة غير المستخدَمة
لا تزيل أداة التحسين إلا الموارد التي لا يشير إليها رمز تطبيقك، ما يعني أنّ أداة التحسين لن تزيل الموارد البديلة لإعدادات الأجهزة المختلفة.
استخدِم السمة resConfigs في "مكوّن Android Gradle" في ملف build.gradle الخاص بوحدة تطبيقك لإزالة ملفات الموارد البديلة التي لا يحتاجها تطبيقك.
على سبيل المثال، إذا كنت تستخدم مكتبة تتضمّن موارد لغوية (مثل "خدمات Google Play")، يتضمّن تطبيقك جميع السلاسل اللغوية المترجَمة للرسائل في هذه المكتبات سواء كانت بقية تطبيقك مترجَمة إلى اللغات نفسها أم لا. للاحتفاظ باللغات التي يتيحها تطبيقك رسميًا فقط، حدِّد هذه اللغات باستخدام السمة resConfigs.
تتم إزالة أي موارد للغات غير محدّدة.
توضّح المقتطفات التالية كيفية حصر مواردك اللغوية على اللغتَين الإنجليزية والفرنسية فقط:
android {
defaultConfig {
...
resourceConfigurations.addAll(listOf("en", "fr"))
}
}
أو
android {
defaultConfig {
...
resConfigs "en", "fr"
}
}
عند نشر تطبيق باستخدام تنسيق حزمة Android App Bundle (AAB)، لا يتم تلقائيًا تنزيل سوى اللغات التي تم ضبطها على جهاز المستخدم عند تثبيت التطبيق. وبالمثل، لا يتم تضمين في عملية التنزيل سوى الموارد التي تتطابق مع كثافة شاشة الجهاز والمكتبات الأصلية التي تتطابق مع واجهة ABI للجهاز. لمزيد من المعلومات، يُرجى الاطّلاع على إعادة تفعيل أنواع حِزم APK الخاصة بالإعدادات أو إيقافها.
بالنسبة إلى التطبيقات القديمة التي يتم إصدارها باستخدام حِزم APK (التي تم إنشاؤها قبل أغسطس 2021)، يمكنك تخصيص كثافة الشاشة أو موارد واجهة ABI لتضمينها في حزمة APK من خلال إنشاء حِزم APK متعددة تستهدف إعدادات أجهزة مختلفة.
تجنُّب التعارضات عند دمج الموارد
تلقائيًا، يدمج "مكوّن إضافي لنظام Gradle المتوافق مع Android" الموارد التي تحمل الاسم نفسه، مثل العناصر القابلة للرسم التي تحمل الاسم نفسه والموجودة في مجلدات موارد مختلفة.
لا يتم التحكّم في هذا السلوك من خلال السمة shrinkResources ولا يمكن إيقافه لأنّ هذا السلوك ضروري لتجنُّب الأخطاء عندما يكون لعدة موارد الاسم الذي يشير إليه الرمز.
لا يحدث دمج الموارد إلا عندما يتشارك ملفان أو أكثر اسم مورد ونوعًا ومؤهلاً متطابقًا. يختار "مكوّن Android Gradle" الملف الذي يحدّده على أنّه الخيار الأفضل من بين الملفات المكرّرة (استنادًا إلى ترتيب الأولوية الموضّح أدناه)، ولا يمرِّر سوى هذا المورد إلى أداة AAPT لتوزيعه في ناتج الإنشاء النهائي.
يبحث "مكوّن Android Gradle" عن الموارد المكرّرة في المواقع التالية:
- الموارد الرئيسية المرتبطة بمجموعة رموز المصدر الرئيسية، والتي تقع عادةً في
src/main/res/ - تراكبات الصيغ، من نوع التصميم وصيغ الإنشاء
- العناصر التابعة لمشروع المكتبة
يدمج "مكوّن Android Gradle" الموارد المكرّرة بترتيب الأولوية المتسلسل التالي:
على سبيل المثال، إذا ظهر مورد مكرّر في كلٍّ من مواردك الرئيسية وصيغة الإنشاء، يختار Gradle المورد في صيغة الإنشاء.
إذا ظهرت موارد متطابقة في مجموعة رموز المصدر نفسها، لا يمكن لـ Gradle دمجها ويظهر خطأ في دمج الموارد. يمكن أن يحدث ذلك إذا حدّدت مجموعات رموز مصدر متعددة في السمة sourceSet في ملف build.gradle الخاص بوحدتك، مثلاً إذا كان كلٌّ من src/main/res/ وsrc/main/res2/ يحتويان على موارد متطابقة.
تحديد المشاكل وحلّها في تقليص الموارد
عند تقليص الموارد، تعرض نافذة الإنشاء ملخّصًا للموارد التي تمت إزالتها من التطبيق. (انقر على تبديل العرض على الجانب الأيمن من النافذة لعرض ناتج النص المفصّل من Gradle). على سبيل المثال:
:android:shrinkDebugResources
Removed unused resources: Resource data reduced from 2570KB to 1711KB: Removed 33%
:android:validateDebugSigning
ينشئ Gradle أيضًا ملفًا تشخيصيًا باسم resources.txt في
<module-name>/build/outputs/mapping/release/ (المجلد نفسه الذي يحتوي على ملفات ناتج ProGuard
). يتضمّن الملف تفاصيل مثل الموارد التي تشير إلى موارد أخرى والموارد المستخدَمة أو التي تمت إزالتها.
على سبيل المثال، لمعرفة سبب بقاء @drawable/ic_plus_anim_016 في تطبيقك، افتح ملف resources.txt وابحث عن اسم الملف هذا. قد تجد أنّه تتم الإشارة إليه من مورد آخر:
16:25:48.005 [QUIET] [system.out] @drawable/add_schedule_fab_icon_anim : reachable=true
16:25:48.009 [QUIET] [system.out] @drawable/ic_plus_anim_016
عليك الآن معرفة سبب إمكانية الوصول إلى @drawable/add_schedule_fab_icon_anim، وإذا بحثت للأعلى، ستجد المورد مُدرَجًا ضمن العنوان The root reachable resources are: في resources.txt.
هذا يعني أنّه هناك مرجعًا للرمز إلى add_schedule_fab_icon_anim، أي تم العثور على رقم تعريف R.drawable الخاص به في الرمز الذي يمكن الوصول إليه.
ما لم تكن تستخدم عملية التحقّق الصارمة، يمكن وضع علامة على أرقام تعريف الموارد على أنّها يمكن الوصول إليها إذا كانت هناك ثوابت سلسلة تبدو وكأنّها قد تُستخدَم لإنشاء أسماء موارد للموارد التي يتم تحميلها ديناميكيًا. في هذه الحالة، إذا بحثت في ناتج الإنشاء عن اسم المورد، قد تظهر لك رسالة مثل هذه:
10:32:50.590 [QUIET] [system.out] Marking drawable:ic_plus_anim_016:2130837506
used because its format-string matches string pool constant ic_plus_anim_%1$d.
إذا ظهرت لك إحدى هذه السلاسل وكنت متأكدًا من أنّه لا يتم استخدام السلسلة لتحميل المورد المحدّد ديناميكيًا، استخدِم السمة tools:discard في ملف keep لإبلاغ نظام التصميم بإزالة المورد.