لتفعيل تحسين التطبيق، يجب استخدام مكتبات متوافقة مع تحسين Android. إذا لم يتم ضبط إحدى المكتبات لتكون متوافقة مع Android، مثلاً إذا كانت تستخدم الانعكاس بدون تجميع قواعد الحفاظ ذات الصلة، قد لا تكون مناسبة لتطبيق Android. توضّح هذه الصفحة سبب ملاءمة بعض المكتبات لتحسين التطبيقات وتقدّم نصائح عامة لمساعدتك في الاختيار.
نصائح عامة عند اختيار المكتبات
استخدِم هذه النصائح للمساعدة في ضمان توافق المكتبات مع ميزة "تحسين التطبيق".
تفضيل إنشاء الرموز على استخدام الانعكاس
اختَر المكتبات التي تستخدم إنشاء الرموز البرمجية (codegen) بدلاً من الانعكاس. باستخدام codegen، يمكن للمحسّن تحديد الرمز الذي يتم استخدامه فعليًا في وقت التشغيل والرمز الذي يمكن إزالته. قد يكون من الصعب معرفة ما إذا كانت إحدى المكتبات تستخدم إنشاء الرموز أو الانعكاس، ولكن هناك بعض المؤشرات التي يمكن أن تساعدك في ذلك، لذا راجِع النصائح.
لمزيد من المعلومات حول إنشاء الرموز البرمجية مقابل الانعكاس، يُرجى الاطّلاع على التحسين لمؤلفي المكتبات.
التحقّق من استخدام الانعكاس (ميزة متقدّمة)
يمكنك معرفة ما إذا كانت إحدى المكتبات تستخدم الانعكاس من خلال فحص الرمز البرمجي الخاص بها. إذا كانت المكتبة تستخدم الانعكاس، تأكَّد من أنّها توفّر قواعد الاحتفاظ المرتبطة بها. من المحتمل أن تستخدم المكتبة ميزة الانعكاس إذا كانت تفعل ما يلي:
- يستخدم هذا التطبيق فئات أو طرقًا من الحزمتَين
kotlin.reflectأوjava.lang.reflect. - يستخدم الدالتَين
Class.forNameأوclassLoader.getClass. - تقرأ التعليقات التوضيحية في وقت التشغيل، مثلاً إذا كانت تخزّن قيمة تعليق توضيحي
باستخدام
val value = myClass.getAnnotation()أوval value = myMethod.getAnnotation()ثم تنفّذ إجراءً باستخدامvalue. يتم استدعاء الطرق باستخدام اسم الطريقة كسلسلة، كما هو موضّح في المثال التالي:
// Calls the private `processData` API with reflection myObject.javaClass.getMethod("processData", DataType::class.java) ?.invoke(myObject, data)
التحقّق من مشاكل التحسين
عند التفكير في استخدام مكتبة جديدة، اطّلِع على أداة تتبُّع المشاكل في المكتبة والمناقشات على الإنترنت لمعرفة ما إذا كانت هناك مشاكل متعلقة بالتصغير أو ضبط إعدادات تحسين التطبيق. إذا كانت هناك بدائل، عليك محاولة البحث عنها. يُرجى مراعاة ما يلي:
- تعمل مكتبات AndroidX والمكتبات الأخرى، مثل Hilt، بشكل جيد مع تحسين التطبيقات لأنّها تستخدم بشكل أساسي إنشاء الرموز البرمجية بدلاً من الانعكاس. وعند استخدامها، يوفّرون الحد الأدنى من قواعد الاحتفاظ لإبقاء الرمز البرمجي المطلوب فقط.
- تستخدم مكتبات التسلسل غالبًا ميزة "الانعكاس" لتجنُّب الرموز النموذجية عند إنشاء مثيل للكائنات أو تسلسلها. بدلاً من الطرق المستندة إلى الانعكاس (مثل Gson لـ JSON)، ابحث عن المكتبات التي تستخدم إنشاء الرموز البرمجية لتجنُّب هذه المشاكل، مثلاً باستخدام Kotlin Serialization أو Moshi مع إنشاء الرموز البرمجية.
- تجنَّب قدر الإمكان المكتبات التي تتضمّن قواعد الاحتفاظ على مستوى الحزمة. يمكن أن تساعد قواعد الاحتفاظ على مستوى الحزمة في حلّ الأخطاء، ولكن يجب في النهاية تحسين قواعد الاحتفاظ الواسعة النطاق للاحتفاظ فقط بالرمز البرمجي المطلوب. لمزيد من المعلومات، اطّلِع على تطبيق التحسينات بشكل تدريجي.
- قبل نشر تطبيق يستخدم مكتبة تابعة لجهة خارجية، استخدِم أداة تحليل إعدادات R8 لتدقيق قواعد الاحتفاظ بالبيانات التي توفّرها. من خلال مراجعة التقرير، يمكنك التأكّد مما إذا كانت قواعد الاحتفاظ بالمكتبة واسعة النطاق بشكل مفرط، ما يمنع R8 من إجراء عمليات تحسين مهمة على قاعدة الرموز البرمجية. يضمن هذا الفحص أنّ المكتبات التي تختارها تتوافق مع أهداف أداء تطبيقك ولا تؤدي إلى تضخّم غير ضروري في الإعدادات.
- يجب ألا تتطلّب منك المكتبات نسخ قواعد الاحتفاظ بالبيانات ولصقها من المستندات في ملف في مشروعك، خاصةً قواعد الاحتفاظ بالبيانات على مستوى الحزمة. وتصبح هذه القواعد عبئًا على مطوّر التطبيق على المدى الطويل، ويصعب تحسينها وتغييرها بمرور الوقت.
تفعيل التحسين بعد إضافة مكتبة جديدة
عند إضافة مكتبة جديدة، فعِّل ميزة التحسين بعد ذلك وتحقّق مما إذا كانت هناك أخطاء. في حال ظهور أخطاء، ابحث عن بدائل لهذه المكتبة أو اكتب قواعد الحفاظ على البيانات. إذا كانت إحدى المكتبات غير متوافقة مع التحسين، يُرجى إرسال تقرير عن خطأ في هذه المكتبة.
فلترة قواعد الاحتفاظ غير الصالحة (متقدّمة)
قواعد الاحتفاظ بالبيانات ترافقية. وهذا يعني أنّه لا يمكن إزالة قواعد معيّنة تتضمّنها تبعية المكتبة، وقد تؤثر في تجميع أجزاء أخرى من تطبيقك. على سبيل المثال، إذا كانت إحدى المكتبات تتضمّن قاعدة لإيقاف تحسينات الرمز، ستؤدي هذه القاعدة إلى إيقاف التحسينات في مشروعك بأكمله.
يجب تجنُّب المكتبات التي تتضمّن قواعد إبقاء تحتفظ برمز برمجي يجب إزالته. ولكن إذا كان عليك استخدامها، يمكنك فلترة القواعد كما هو موضّح في الرمز التالي:
// If you're using AGP 8.4 and higher
buildTypes {
release {
optimization.keepRules {
it.ignoreFrom("com.somelibrary:somelibrary")
}
}
}
// If you're using AGP 7.3-8.3
buildTypes {
release {
optimization.keepRules {
it.ignoreExternalDependencies("com.somelibrary:somelibrary")
}
}
}
دراسة حالة: لماذا يتعطّل Gson عند إجراء تحسينات؟
Gson هي مكتبة نشر على نحو متسلسِل غالبًا ما تتسبّب في حدوث مشاكل في تحسين التطبيق لأنّها تستخدم الانعكاس بشكل كبير. يوضّح مقتطف الرمز التالي كيفية استخدام Gson عادةً، ما قد يؤدي إلى حدوث أعطال أثناء وقت التشغيل. لاحظ أنّه عند استخدام Gson للحصول على قائمة بعناصر User، لن تحتاج إلى استدعاء الدالة الإنشائية أو تمرير مصنع إلى الدالة fromJson(). إنّ إنشاء فئات يحدّدها التطبيق أو استخدامها بدون أيّ مما يلي يشير إلى أنّ إحدى المكتبات قد تستخدم انعكاسًا مفتوحًا:
- فئة التطبيق التي تنفِّذ مكتبة أو واجهة أو فئة عادية
- مكوّن إضافي لإنشاء الرموز البرمجية مثل KSP
class User(val name: String)
class UserList(val users: List<User>)
// This code runs in debug mode, but crashes when optimizations are enabled
Gson().fromJson("""[{"name":"myname"}]""", User::class.java).toString()
للتعرّف على طريقة عمل R8 على Gson، اطّلِع على قواعد المستهلك في Gson. عندما يحلّل R8 هذا الرمز البرمجي ولا يجد أي مثيل من UserList أو User، يمكنه إعادة تسمية الحقول أو إزالة الدوال الإنشائية التي يبدو أنّها غير مستخدَمة، ما يؤدي إلى تعطُّل تطبيقك. إذا كنت تستخدم أي مكتبات أخرى بطرق مشابهة، عليك التأكّد من أنّها لن تتداخل مع عملية تحسين التطبيق، وفي حال حدوث ذلك، تجنَّب استخدامها.
استخدام @SerializedName مع إصدارات Gson الأحدث
لتحديد نماذج البيانات بطريقة متوافقة مع قواعد Gson الخاصة بالمستهلكين،
أضِف تعليقًا توضيحيًا إلى الحقول باستخدام @SerializedName، كما هو موضّح في المقتطف التالي:
import com.google.gson.annotations.SerializedName
class User(@SerializedName("name") val name: String)
class UserList(@SerializedName("users") val users: List<User>)
باستخدام التعليق التوضيحي @SerializedName، يمكنك السماح لأداة R8 بمطابقة فئات النماذج مع قواعد الاحتفاظ المضمّنة في الإصدار 2.11.0 من Gson والإصدارات الأحدث.
يحافظ R8 تلقائيًا على الحقول التي تمت إضافة تعليقات توضيحية إليها والمنشئات الضرورية، ما يتيح لك الاعتماد على القواعد المجمّعة في المكتبة بدون الحاجة إلى الحفاظ على إعدادات ProGuard اليدوية في مشروعك.
يُرجى العِلم أنّ Room وHilt وMoshi مع إنشاء الرموز تنشئ أنواعًا محدّدة في التطبيق، ولكنها تستخدم إنشاء الرموز لتجنُّب الحاجة إلى الانعكاس.