عند تفعيل تحسين التطبيق، يختلف السلوك التلقائي لأداة التحسين باختلاف إصدارات R8.
- باستخدام لغة DSL المعدَّلة المتوفّرة من الإصدار 9.3 من "المكوّن الإضافي لنظام Gradle المتوافق مع Android" والإصدارات الأحدث، يتم تفعيل ميزة تصغير حجم الموارد تلقائيًا عند تفعيل ميزة التحسين. يُرجى العِلم أنّه لا يزال بإمكانك استخدام لغة DSL القديمة التي تتطلّب تفعيل تحسين الرموز والموارد بشكل منفصل.
في الإصدارات الأقدم من الإصدار 9.3 من "المكوّن الإضافي لنظام Gradle المتوافق مع Android"، يطلب الإعداد
isShrinkResources = trueمن أداة التحسين إزالة الموارد غير المستخدَمة، ما يساعد في تقليل حجم تطبيقك. لا يمكن تقليل حجم الموارد إلا بالتزامن مع تقليل حجم الرموز، لذا إذا كنت تعمل على تحسين الموارد، عليك أيضًا ضبطisMinifyEnabled = true.
الإصدار 9.3 من "مكوّن Android الإضافي لنظام Gradle" أو الإصدارات الأحدث (Kotlin)
buildTypes {
release {
optimization {
enable = true // Enables code and resource optimizations.
}
}
}
إصدار AGP 9.3 أو إصدار أحدث (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
...
}
}
إذا كنت تريد الاحتفاظ بموارد معيّنة أو تجاهلها، أنشئ ملف keep بتنسيق XML في موارد مشروعك، مثل res/raw/keep_my_package.xml. يحتوي ملف الاحتفاظ على المكوّنات التالية:
- العلامة
<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" />
قد يبدو تحديد الموارد التي سيتم تجاهلها أمرًا غير ضروري عندما يمكنك حذفها بدلاً من ذلك، ولكن يمكن أن يكون تجاهل الموارد مفيدًا عند استخدام صيغ الإنشاء.
استهداف صيغ محدّدة من الإصدار
لإزالة الموارد في بعض تنويعات التصميم فقط، ضَع جميع مواردك في دليل المشروع المشترك، ثم أنشِئ ملف keep_my_package_build_variant.xml مختلفًا لكل تنويعة تصميم في دليل موارد تنويعة التصميم. في ملف keep، حدِّد يدويًا الموارد التي تريد إزالتها عندما يبدو أنّ أحد الموارد مستخدَم في الرمز (وبالتالي لن تتم إزالته بواسطة أداة التصغير)، ولكنك تعلم أنّه لن يتم استخدامه فعليًا في تنويعة التصميم المحدّدة.
إزالة المراجع البديلة غير المستخدَمة
لا يزيل المحسِّن سوى الموارد التي لا يشير إليها رمز تطبيقك، ما يعني أنّه لن يزيل الموارد البديلة لإعدادات الأجهزة المختلفة.
استخدِم السمة resConfigs في Android Gradle في ملف build.gradle الخاص بوحدة تطبيقك لإزالة ملفات الموارد البديلة التي لا يحتاج إليها تطبيقك.
على سبيل المثال، إذا كنت تستخدم مكتبة تتضمّن موارد لغوية (مثل "خدمات Google Play")، سيتضمّن تطبيقك جميع سلاسل اللغة المترجَمة للرسائل في تلك المكتبات، سواء تمت ترجمة بقية تطبيقك إلى اللغات نفسها أم لا. للاحتفاظ فقط باللغات التي يتيحها تطبيقك رسميًا، حدِّد هذه اللغات باستخدام السمة resConfigs.
تتم إزالة أي مراجع للغات غير محدّدة.
توضّح المقتطفات التالية كيفية حصر موارد اللغة على الإنجليزية والفرنسية فقط:
android {
defaultConfig {
...
resourceConfigurations.addAll(listOf("en", "fr"))
}
}
أو
android {
defaultConfig {
...
resConfigs "en", "fr"
}
}
عند نشر تطبيق باستخدام تنسيق "حِزمة تطبيق Android" (AAB)، لا يتم تلقائيًا تنزيل سوى اللغات التي تم ضبطها على جهاز المستخدم عند تثبيت التطبيق. وبالمثل، لا يتم تضمين سوى الموارد التي تتطابق مع كثافة الشاشة على الجهاز والمكتبات الأصلية التي تتطابق مع واجهة التطبيق الثنائية (ABI) على الجهاز في عملية التنزيل. لمزيد من المعلومات، يُرجى الاطّلاع على إعادة تفعيل أنواع حِزم APK الخاصة بالإعدادات أو إيقافها.
بالنسبة إلى التطبيقات القديمة التي يتم إصدارها باستخدام حِزم APK (التي تم إنشاؤها قبل أغسطس 2021)، يمكنك تخصيص موارد كثافة الشاشة أو واجهة التطبيق الثنائية (ABI) لتضمينها في حزمة APK من خلال إنشاء حِزم APK متعددة تستهدف إعدادات مختلفة للأجهزة.
تجنُّب التعارضات عند دمج الموارد
تلقائيًا، يدمج مكوّن إضافي لنظام Gradle المتوافق مع Android الموارد التي تحمل الاسم نفسه، مثل العناصر القابلة للرسم التي تحمل الاسم نفسه والموجودة في مجلدات موارد مختلفة.
لا يمكن التحكّم في هذا السلوك باستخدام السمة shrinkResources ولا يمكن إيقافه لأنّه ضروري لتجنُّب حدوث أخطاء عندما تتضمّن موارد متعدّدة الاسم الذي يشير إليه الرمز.
لا يحدث دمج الموارد إلا عندما تتشارك ملفان أو أكثر في اسم ونوع ومحدّد مطابقين للمورد. يختار AGP الملف الذي يحدّده على أنّه الخيار الأفضل من بين الملفات المكرّرة (استنادًا إلى ترتيب الأولوية الموضّح أدناه)، ولا يمرّر سوى هذا المورد إلى AAPT لتوزيعه في عنصر الإصدار النهائي.
يبحث AGP عن الموارد المكرّرة في المواقع التالية:
- الموارد الرئيسية المرتبطة بمجموعة رموز المصدر الرئيسية، والتي تقع عادةً في
src/main/res/ - تراكبات الصيغ، من نوع التصميم وصيغ الإصدار
- الاعتماديات الخاصة بمشاريع المكتبات
يدمج "المكوّن الإضافي لنظام Gradle المتوافق مع Android" الموارد المكرّرة حسب ترتيب الأولوية المتسلسل التالي:
على سبيل المثال، إذا ظهرت مادة عرض مكرّرة في كل من مواد العرض الرئيسية وإصدار البناء، سيختار 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،
وإذا بحثت للأعلى، ستجد المرجع مُدرَجًا ضمن العنوان
المراجع الأساسية التي يمكن الوصول إليها هي: في 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 لإعلام نظام التصميم بإزالة المورد.