ضبط قواعد الاحتفاظ ببيانات R8 وتحديد المشاكل فيها وحلّها
يستغرق الاطّلاع على المقال 7 دقائق
في عملية تطوير تطبيقات Android الحديثة، يُعدّ توفير تطبيق صغير وسريع وآمن من التوقعات الأساسية للمستخدمين. الأداة الأساسية التي يستخدمها نظام تصميم Android لتحقيق ذلك هي أداة التحسين R8 ، وهي برنامج التجميع الذي يتعامل مع الرموز والموارد غير المستخدَمة لإزالة البيانات غير الضرورية، وإعادة تسمية الرموز أو تقليل حجمها، وتحسين التطبيق.
يُعدّ تفعيل R8 خطوة مهمة في إعداد تطبيق للإصدار، ولكنّه يتطلّب من المطوّرين تقديم إرشادات في شكل "قواعد الاحتفاظ".
بعد قراءة هذه المقالة، يمكنك مشاهدة فيديو "أسبوع تسليط الضوء على الأداء" حول تفعيل أداة تحسين R8 وتصحيح أخطائها وحلّ مشاكلها على YouTube.
أهمية قواعد الاحتفاظ بالبيانات
تنشأ الحاجة إلى كتابة قواعد Keep Rules من تعارض أساسي: R8 هي أداة تحليل ثابت، ولكن تطبيقات Android تعتمد غالبًا على أنماط التنفيذ الديناميكي، مثل الانعكاس أو عمليات الاستدعاء داخل الرمز البرمجي الأصلي وخارجه باستخدام JNI (واجهة Java الأصلية).
تنشئ أداة R8 رسمًا بيانيًا للرموز البرمجية المستخدَمة من خلال تحليل عمليات الاستدعاء المباشر. عند الوصول إلى الرمز بطريقة ديناميكية، لا يمكن للتحليل الثابت في R8 توقّع ذلك، وسيصنّف هذا الرمز على أنّه غير مستخدَم ويزيله، ما يؤدي إلى حدوث أعطال أثناء وقت التشغيل.
قاعدة الاحتفاظ هي تعليمات صريحة لمترجم R8، تنص على ما يلي: "هذا الصنف أو الطريقة أو الحقل المحدّد هو نقطة دخول سيتم الوصول إليها بشكل ديناميكي في وقت التشغيل. عليك الاحتفاظ بها، حتى إذا لم تتمكّن من العثور على إشارة مباشرة إليها".
يمكنك الاطّلاع على الدليل الرسمي لمعرفة المزيد من التفاصيل حول قواعد الاحتفاظ.
مكان كتابة "قواعد الاحتفاظ"
تتم كتابة قواعد الاحتفاظ المخصّصة لأحد التطبيقات في ملف نصي. وفقًا للاصطلاح، يُطلق على هذا الملف الاسم proguard-rules.pro ويقع في جذر وحدة التطبيق أو المكتبة. يتم بعد ذلك تحديد هذا الملف في نوع التصميم release من ملف build.gradle.kts في الوحدة.
release {
isShrinkResources = true
isMinifyEnabled = true
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro",
)
}استخدام الملف التلقائي الصحيح
تستورد الطريقة getDefaultProguardFile مجموعة تلقائية من القواعد التي توفّرها حزمة تطوير البرامج (SDK) لنظام التشغيل Android. عند استخدام ملف غير صحيح، قد لا يكون تطبيقك محسَّنًا. احرص على استخدام proguard-android-optimize.txt. يوفر هذا الملف "قواعد الاحتفاظ" التلقائية لمكوّنات Android العادية ويتيح تحسينات R8 على الرموز. لا يوفّر الإصدار القديم من proguard-android.txt سوى قواعد Keep، ولكنه لا يفعّل تحسينات R8.
بما أنّ هذه المشكلة تؤثر بشكل كبير في الأداء، سنبدأ بتنبيه المطوّرين بشأن استخدام الملف غير الصحيح، وذلك بدءًا من الإصدار 3 من تحديثات استوديو Android Narwhal. واعتبارًا من الإصدار 9.0 من المكوّن الإضافي لنظام Gradle المتوافق مع Android، لن نتيح استخدام ملف proguard-android.txt القديم. لذا، احرص على الترقية إلى الإصدار المحسّن.
كيفية كتابة قواعد Keep
تتألف قاعدة الحفظ من ثلاثة أجزاء رئيسية:
- خيار مثل
-keepأو-keepclassmembers - المعدّلات الاختيارية مثل
allowshrinking - مواصفات فئة تحدّد الرمز المطلوب مطابقته
للاطّلاع على البنية الكاملة والأمثلة، يُرجى الرجوع إلى الإرشادات حول إضافة قواعد الاحتفاظ.
مضادات أنماط قواعد الاحتفاظ بالبيانات
من المهم معرفة أفضل الممارسات، بالإضافة إلى الأنماط المضادة. غالبًا ما تنشأ هذه الأنماط المضادة من حالات سوء فهم أو اختصارات لتحديد المشاكل وحلّها، ويمكن أن تكون كارثية بالنسبة إلى أداء الإصدار المتاح.
الخيارات العامّة
هذه العلامات هي مفاتيح تبديل عامة يجب عدم استخدامها مطلقًا في بنية الإصدار. وهي مخصّصة فقط لتصحيح الأخطاء المؤقت بهدف عزل المشكلة.
يؤدي استخدام -dontotptimize إلى إيقاف تحسينات الأداء التي توفّرها الأداة R8، ما يؤدي إلى إبطاء التطبيق.
عند استخدام -dontobfuscate، يتم إيقاف جميع عمليات إعادة التسمية، وعند استخدام -dontshrink، يتم إيقاف إزالة الرموز البرمجية غير النشطة. تؤدي كلتا القاعدتين العامّتين إلى زيادة حجم التطبيق.
تجنَّب استخدام هذه العلامات العامة في بيئة التشغيل الفعلي قدر الإمكان للحصول على تجربة أفضل للمستخدمين.
قواعد الاحتفاظ الواسعة النطاق بشكل مفرط
إنّ أسهل طريقة لإبطال مزايا R8 هي كتابة قواعد Keep واسعة النطاق. تضمن قواعد مثل القاعدة أدناه عدم تصغير المحسِّن R8 لأي فئة في هذه الحزمة أو أي من حِزمها الفرعية، وعدم تشويشها أو تحسينها. يؤدي ذلك إلى إزالة مزايا R8 بالكامل من تلك الحزمة بأكملها. جرِّب كتابة "قواعد الاحتفاظ" ضيقة ومحددة بدلاً من ذلك.
-keep class com.example.package.** { *;} // WIDE KEEP RULES CAUSE PROBLEMSعامل النفي (!)
يبدو أنّ عامل النفي (!) هو طريقة فعّالة لاستبعاد حزمة من إحدى القواعد. لكنّ الأمر ليس بهذه البساطة. لِنأخذ المثال التالي:
-keep class !com.example.my_package.** { *; } // USE WITH CAUTIONقد تعتقد أنّ هذه القاعدة تعني "لا تحتفظ بالفئات فيcom.example.package"، ولكنّها تعني في الواقع "احتفظ بكل فئة وطريقة وسمة في التطبيق بأكمله غير الموجودة في com.example.package". إذا كان ذلك مفاجئًا لك، من الأفضل التحقّق من أي عمليات نفي في إعدادات R8.
قواعد مكرّرة لمكوّنات Android
من الأخطاء الشائعة الأخرى إضافة "قواعد الإبقاء" يدويًا إلى Activities أو Services أو BroadcastReceivers في تطبيقك. هذا الإجراء غير ضروري. يتضمّن ملف proguard-android-optimize.txt التلقائي القواعد ذات الصلة لكي تعمل هذه المكوّنات العادية في Android بدون أي إعدادات إضافية.
توفّر العديد من المكتبات أيضًا "قواعد الاحتفاظ" الخاصة بها. لذلك، لن تحتاج إلى كتابة قواعد خاصة بهذه الحالات. في حال حدوث مشكلة في "قواعد الاحتفاظ" من مكتبة تستخدمها، من الأفضل التواصل مع مؤلف المكتبة لمعرفة المشكلة.
أفضل الممارسات المتعلّقة بقاعدة Keep
بعد أن تعرّفت على ما لا يجب فعله، لنتحدّث الآن عن أفضل الممارسات.
كتابة "قواعد Keep" محدّدة
يجب أن تكون قواعد الاحتفاظ الجيدة ضيقة ومحددة قدر الإمكان. ويجب أن تحتفظ هذه القواعد بما هو ضروري فقط، ما يسمح لأداة R8 بتحسين كل ما عدا ذلك.
| القاعدة | الجودة |
|---|---|
| منخفض: يتم الاحتفاظ بالحزمة بأكملها وحِزمها الفرعية |
| منخفض: يحتفظ بفئة كاملة من المرجّح أنّها لا تزال واسعة جدًا |
-keepclassmembers class com.example.MyClass {
private java.lang.String secretMessage;
public void onNativeEvent(java.lang.String);
} | عالية: يتم الاحتفاظ بالطُرق والسمات ذات الصلة فقط من فئة معيّنة |
استخدام الأسلاف المشتركين
بدلاً من كتابة قواعد Keep منفصلة لنماذج بيانات مختلفة متعددة، اكتب قاعدة واحدة تستهدف صنفًا أساسيًا أو واجهة مشتركة. تطلب القاعدة أدناه من R8 الاحتفاظ بأي عناصر من الفئات التي تنفّذ هذه الواجهة، وهي قابلة للتوسيع بشكل كبير.
# Keep all fields of any class that implements SerializableModel
-keepclassmembers class * implements com.example.models.SerializableModel {
<fields>;
}استخدام التعليقات التوضيحية لاستهداف صفوف متعددة
أنشئ تعليقًا توضيحيًا مخصّصًا (مثل @Serialize) واستخدِمه "لوضع علامة" على الفئات التي تحتاج إلى الاحتفاظ بحقولها. هذا نمط آخر واضح وتصريحي وقابل للتوسّع بشكل كبير. يمكنك إنشاء "قواعد Keep" للتعليقات التوضيحية الحالية من الأُطر التي تستخدمها أيضًا.
# Keep all fields of any class annotated with @Serialize
-keepclassmembers class * {
@com.example.annotations.Serialize <fields>;
}اختيار خيار Keep المناسب
يُعدّ خيار "الاحتفاظ" الجزء الأكثر أهمية في القاعدة. قد يؤدي اختيار الخيار غير الصحيح إلى إيقاف التحسين بدون داعٍ.
| خيار الاحتفاظ | الإجراءات التي ينفّذها |
-keep | يمنع إزالة الفئة والأعضاء المذكورين في البيان أو إعادة تسميتهم. |
-keepclassmembers | يمنع الأعضاء المحدّدين من إزالتهم أو إعادة تسميتهم، ولكنّه يسمح بإزالة الصف نفسه فقط في الصفوف التي لم تتم إزالتها بطريقة أخرى. |
-keepclasseswithmembers | الدمج: يتم الاحتفاظ بالفئة وعناصرها فقط إذا كانت جميع العناصر المحدّدة متوفّرة. |
يمكنك الاطّلاع على مزيد من المعلومات حول خيار "الاحتفاظ" في مستندات خيارات الاحتفاظ.
السماح بالتحسين باستخدام أدوات التعديل
تؤدي المعدِّلات، مثل allowshrinking وallowobfuscation، إلى تخفيف قاعدة -keep واسعة النطاق، ما يمنح R8 إمكانية التحسين مرة أخرى. على سبيل المثال، إذا كانت مكتبة قديمة تجبرك على استخدام -keep في فئة بأكملها، قد تتمكّن من استعادة بعض التحسينات من خلال السماح بالتصغير والتشويش:
# Keep this class, but allow R8 to remove it if it's unused and allow R8 to rename it. -keep,allowshrinking,allowobfuscation class com.example.LegacyClass
إضافة خيارات عامة لتحسين الأداء بشكل إضافي
بالإضافة إلى "قواعد الاحتفاظ"، يمكنك إضافة علامات عامة إلى ملف إعدادات R8 لتشجيع المزيد من التحسين.
-repackageclasses هو خيار فعّال يوجّه R8 إلى نقل جميع الفئات التي تم تشويشها إلى حزمة واحدة. يؤدي ذلك إلى توفير مساحة كبيرة في ملف DEX من خلال إزالة سلاسل أسماء الحِزم المكرّرة.
تسمح -allowaccessmodification لبرنامج R8 بتوسيع نطاق الوصول (على سبيل المثال، من private إلى public) لتفعيل التضمين الأكثر فعالية. يتم تفعيل هذا الخيار تلقائيًا عند استخدام proguard-android-optimize.txt.
تحذير: يجب على مطوّري المكتبات عدم إضافة علامات التحسين العامة هذه إلى قواعد المستهلكين، لأنّه سيتم تطبيقها بشكل إلزامي على التطبيق بأكمله.
ولزيادة الوضوح، سنبدأ في الإصدار 9.0 من المكوّن الإضافي لنظام Gradle المتوافق مع Android بتجاهل علامات التحسين العامة من المكتبات تمامًا.
أفضل الممارسات للمكتبات
تعتمد جميع تطبيقات Android على المكتبات بطريقة أو بأخرى. لنتحدّث الآن عن أفضل الممارسات المتعلّقة بالمكتبات.
لمطوّري المكتبات
إذا كانت مكتبتك تستخدم الانعكاس أو JNI، تقع على عاتقك مسؤولية توفير قواعد Keep اللازمة للمستهلكين. يتم وضع هذه القواعد في ملف consumer-rules.pro، ثم يتم تجميعها تلقائيًا داخل ملف AAR الخاص بالمكتبة.
android {
defaultConfig {
consumerProguardFiles("consumer-rules.pro")
}
...
}لمستخدمي المكتبة
فلترة "قواعد Keep" التي تتضمّن مشاكل
إذا كان عليك استخدام مكتبة تتضمّن قواعد Keep Rules إشكالية، يمكنك فلترتها في ملف build.gradle.kts بدءًا من الإصدار 9.0 من AGP، ما يطلب من R8 تجاهل القواعد الواردة من اعتمادية معيّنة.
release {
optimization.keepRules {
// Ignore all consumer rules from this specific library
it.ignoreFrom("com.somelibrary:somelibrary")
}
}أفضل قاعدة احتفاظ هي عدم وجود قاعدة احتفاظ
تتمثّل استراتيجية إعدادات R8 النهائية في إزالة الحاجة إلى كتابة قواعد الاحتفاظ تمامًا. يمكن تحقيق ذلك في العديد من التطبيقات من خلال اختيار مكتبات حديثة تعطي الأولوية لإنشاء الرموز على التفكير المجرد. باستخدام ميزة إنشاء الرموز البرمجية، يمكن لأداة التحسين تحديد الرموز البرمجية المستخدَمة فعليًا في وقت التشغيل والرموز البرمجية التي يمكن إزالتها بسهولة أكبر. عدم استخدام أي انعكاس ديناميكي يعني أيضًا عدم وجود نقاط دخول "مخفية"، وبالتالي لا حاجة إلى قواعد Keep. عند اختيار مكتبة جديدة، ننصحك دائمًا باختيار حلّ يستخدم إنشاء الرموز البرمجية بدلاً من الانعكاس.
لمزيد من المعلومات حول كيفية اختيار المكتبات، يُرجى الاطّلاع على مقالة اختيار المكتبة بحكمة.
تحديد المشاكل وحلّها في إعدادات R8
عندما تزيل أداة R8 رمزًا كان من المفترض الاحتفاظ به، أو إذا كان حجم حزمة APK أكبر من المتوقع، استخدِم هذه الأدوات لتشخيص المشكلة.
البحث عن قواعد Keep المكرّرة والعامة
بما أنّ R8 يدمج القواعد من عشرات المصادر، قد يصعب معرفة مجموعة القواعد "النهائية". تؤدي إضافة هذا الخيار إلى ملف proguard-rules.pro إلى إنشاء تقرير كامل:
# Outputs the final, merged set of rules to the specified file -printconfiguration build/outputs/logs/configuration.txt
يمكنك البحث في هذا الملف للعثور على قواعد مكرّرة أو تتبُّع قاعدة تتضمّن مشكلة (مثل -dontoptimize) والرجوع إلى المكتبة المحدّدة التي تضمّنتها.
Ask R8: Why are you keeping this?
إذا كان صف تتوقّع إزالته لا يزال في تطبيقك، يمكن أن يوضّح لك R8 السبب. ما عليك سوى إضافة هذه القاعدة:
# Asks R8 to explain why it's keeping a specific class class com.example.MyUnusedClass -whyareyoukeeping
أثناء عملية الإنشاء، ستعرض أداة R8 سلسلة المراجع الدقيقة التي أدّت إلى الاحتفاظ بهذا الصف، ما يتيح لك تتبُّع المرجع وتعديل قواعدك.
للحصول على دليل كامل، يُرجى الاطّلاع على قسم تحديد المشاكل في R8 وحلّها.
الخطوات التالية
R8 هي أداة فعّالة لتحسين أداء تطبيقات Android. وتعتمد فعاليته على فهم صحيح لطريقة عمله كمحرّك تحليل ثابت.
من خلال كتابة قواعد محدّدة على مستوى الأعضاء، والاستفادة من العناصر الأصلية والتعليقات التوضيحية، واختيار خيارات الاحتفاظ المناسبة بعناية، يمكنك الاحتفاظ بما هو ضروري بالضبط. تتمثّل الممارسة الأكثر تقدّمًا في إلغاء الحاجة إلى القواعد تمامًا من خلال اختيار مكتبات حديثة مستندة إلى إنشاء الرموز البرمجية بدلاً من المكتبات السابقة المستندة إلى الانعكاس.
أثناء متابعة "أسبوع تسليط الضوء على الأداء"، احرص على مشاهدة فيديو "أسبوع تسليط الضوء" اليوم على YouTube ومواصلة تحدّي R8. استخدِم الهاشتاج #optimizationEnabled لطرح أي أسئلة حول تفعيل R8 أو تحديد المشاكل وحلّها. نحن في الخدمة.
حان الوقت للاطّلاع على المزايا بنفسك.
ندعوك إلى تفعيل الوضع الكامل لأداة R8 في تطبيقك اليوم.
- اتّبِع أدلة المطوّرين للبدء: تفعيل تحسين التطبيق.
- تحقَّق مما إذا كنت لا تزال تستخدم
proguard-android.txtواستبدِله بـproguard-android-optimize.txt. - بعد ذلك، قِس التأثير. لا تكتفِ بالشعور بالفرق، بل تأكَّد منه. يمكنك قياس تحسّن الأداء من خلال تعديل الرمز من نموذج تطبيق Macrobenchmark التجريبي على GitHub لقياس أوقات بدء التشغيل قبل وبعد التعديل.
نحن على ثقة بأنّك ستلاحظ تحسّنًا ملحوظًا في أداء تطبيقك.
يمكنك أيضًا استخدام الهاشتاغ #AskAndroid لطرح أسئلتك. يتابع خبراء Google أسئلتك ويجيبون عنها طوال الأسبوع.
ترقَّبوا مشاركتنا غدًا معلومات حول ميزة "التحسين المستند إلى الملف الشخصي" باستخدام "ملفات المرجع" و"ملفات بدء التشغيل"، وسنشارك أيضًا معلومات حول كيفية تحسُّن أداء العرض في Compose خلال الإصدارات السابقة، بالإضافة إلى اعتبارات الأداء المتعلقة بالعمل في الخلفية.
-
أخبار المنتجاتنحن في Google Play ملتزمون بتقديم أفضل تجربة ممكنة للمستخدمين، مع ضمان توفير الأدوات والمرونة اللازمة للمطوّرين لتحقيق النجاح.
Paul Feng • يستغرق الاطّلاع على المقال 3 دقائق -
أخبار المنتجاتفي العام الماضي، أطلقنا ميزة التحقّق من هوية مطوّر تطبيقات Android لتعزيز أمان المنظومة المتكاملة ومنع الجهات المسيئة من إخفاء هويتها لنشر تطبيقات ضارة.
Matthew Forsythe • مدّة القراءة: دقيقتان -
أخبار المنتجاتبدءًا من التراكبات المعزّزة إلى البيئات الغامرة بالكامل، تتوسّع منظومة Android XR المتكاملة بسرعة، وتتوفّر سماعة الرأس Samsung Galaxy XR اليوم.
Stevan Silva, Vinny DaSilva • يستغرق الاطِّلاع على المقال 3 دقائق
يمكنك تلقّي أحدث الإحصاءات حول تطوير تطبيقات Android في بريدك الوارد أسبوعيًا.