التحسين لمؤلفي المكتبات

بصفتك مؤلف مكتبة، عليك التأكّد من أنّه يمكن لمطوّري التطبيقات دمج مكتبتك في تطبيقاتهم بسهولة مع الحفاظ على جودة عالية لتجربة مستخدمي التطبيقات النهائيين. يجب التأكّد من توافق مكتبتك مع تحسين Android بدون إعداد إضافي، أو توضيح أنّ المكتبة قد تكون غير مناسبة للاستخدام على Android.

تستهدف هذه المستندات مطوّري المكتبات المنشورة، ولكنها قد تكون مفيدة أيضًا لمطوّري وحدات المكتبات الداخلية في تطبيق كبير ومكوّن من وحدات.

إذا كنت مطوّر تطبيقات وتريد التعرّف على كيفية تحسين تطبيق Android، اطّلِع على مقالة تفعيل ميزة تحسين التطبيق. للتعرّف على المكتبات المناسبة للاستخدام، اطّلِع على مقالة اختيار المكتبات بحكمة.

استخدام codegen بدلاً من ميزة "العرض المرجعي"

استخدِم إنشاء الرموز البرمجية (codegen) بدلاً من ميزة "العرض المرئي" كلما أمكن. إنّ إنشاء الرموز البرمجية والتفكير في الرمز البرمجي هما من الأساليب الشائعة لتجنُّب استخدام رمز برمجي عادي عند البرمجة، ولكنّ إنشاء الرموز البرمجية أكثر توافقًا مع أدوات تحسين التطبيقات، مثل R8:

  • باستخدام codegen، يتم تحليل الرمز البرمجي وتعديله أثناء عملية الإنشاء. وبما أنّه لا تتوفّر أي تعديلات كبيرة بعد وقت الترجمة، يعرف المحسِّن الرمز البرمجي المطلوب في النهاية وما يمكن إزالته بأمان.
  • من خلال ميزة "التفكير"، يتم تحليل الرمز البرمجي ومعالجته أثناء التشغيل. ولأنّ الرمز المبرمَج لا يتم الانتهاء منه فعليًا إلى أن يتم تنفيذه، لا يعرف المحسِّن الرمز المبرمَج الذي يمكن إزالته بأمان. ومن المرجّح أن تزيل هذه العملية الرمز البرمجي المستخدَم ديناميكيًا من خلال التأمل أثناء وقت التشغيل، ما يؤدي إلى تعطُّل التطبيق لدى المستخدمين.

تستخدم العديد من المكتبات الحديثة codegen بدلاً من ميزة التأمل. اطّلِع على KSP لمعرفة نقطة دخول شائعة تستخدمها Room وDagger2 وغيرها الكثير.

الحالات التي يكون فيها الانعكاس مقبولًا

إذا كان عليك استخدام ميزة "الانعكاس"، يجب عدم استخدامها إلا في أيّ من المحتوى التالي:

  • أنواع مستهدَفة محدّدة (منفّذو الواجهات أو الفئات الفرعية المحدّدة)
  • رمز يستخدم تعليقًا توضيحيًا محدّدًا لوقت التشغيل

يؤدي استخدام ميزة "العرض المرجعي" بهذه الطريقة إلى الحد من تكلفة وقت التشغيل، ويتيح كتابة قواعد الاحتفاظ بالمستهلكين المستهدَفين.

هذا الشكل المحدّد والمستهدف من التوسّع هو نمط يمكنك مشاهدته في كلٍّ من إطار عمل Android (على سبيل المثال، عند تضخيم الأنشطة وعناصر العرض والعناصر القابلة للرسم) ومكتبات AndroidX (على سبيل المثال، عند إنشاء WorkManager ListenableWorkers أو RoomDatabases). في المقابل، فإنّ البنية المفتوحة لتمثيل Gson غير مناسبة للاستخدام في تطبيقات Android.

كتابة قواعد الاحتفاظ بالبيانات للمستهلك

يجب أن تحزِّم المكتبات قواعد الاحتفاظ ببيانات "المستهلك" التي تستخدم التنسيق نفسه المستخدَم في قواعد الاحتفاظ ببيانات التطبيقات. يتم تجميع هذه القواعد في عناصر المكتبة (ملفّات AAR أو JAR) ويتم استخدامها تلقائيًا أثناء تحسين تطبيق Android عند استخدام المكتبة.

مكتبات ميزة "الاقتراحات المطبّقة تلقائيًا"

لإضافة قواعد المستهلك لمكتبة AAR، استخدِم الخيار consumerProguardFiles في نص إنشاء وحدة مكتبة Android. لمزيد من المعلومات، يُرجى الاطّلاع على الإرشادات حول إنشاء وحدات المكتبة.

Kotlin

android {
    defaultConfig {
        consumerProguardFiles("consumer-proguard-rules.pro")
    }
    ...
}

رائع

android {
    defaultConfig {
        consumerProguardFiles 'consumer-proguard-rules.pro'
    }
    ...
}

مكتبات JAR

لتجميع القواعد مع مكتبة Kotlin/Java التي يتم شحنها كملف JAR، ضَع ملف القواعد في الدليل META-INF/proguard/ لملف JAR النهائي، مع أي اسم ملف. على سبيل المثال، إذا كان الرمز البرمجي في <libraryroot>/src/main/kotlin، ضَع ملف consumer rules في <libraryroot>/src/main/resources/META-INF/proguard/consumer-proguard-rules.pro وسيتم تجميع القواعد في الموقع الصحيح في حزمة JAR الناتجة.

تأكَّد من أنّ حِزم JAR النهائية تضمّ القواعد بشكل صحيح من خلال التحقّق من أنّ القواعد في الدليل META-INF/proguard.

تحسين عملية إنشاء مكتبة AAR (متقدّمة)

بشكل عام، يجب عدم تحسين إصدار مكتبة مباشرةً لأنّه يمكن إجراء عدد محدود جدًا من التحسينات في وقت إنشاء المكتبة. لا يمكن لـ IDE R8 معرفة كيفية استخدام جميع طرق المكتبة والمَعلمات التي يتم تمريرها إلا أثناء معالجة ملف APK للتطبيق، وذلك عند تضمين مكتبة كجزء من التطبيق. بصفتك مطوّر مكتبة، عليك التفكير في مراحل متعددة من التحسين والحفاظ على السلوك، سواء في وقت إنشاء المكتبة أو التطبيق، قبل تحسين هذه المكتبة.

إذا كنت لا تزال تريد تحسين مكتبتك في وقت التصميم، يتيح المكوّن الإضافي لنظام Gradle المتوافق مع Android إجراء ذلك.

Kotlin

android {
    buildTypes {
        release {
            isMinifyEnabled = true
            proguardFiles(
                getDefaultProguardFile("proguard-android-optimize.txt"),
                "proguard-rules.pro"
            )
        }
        configureEach {
            consumerProguardFiles("consumer-rules.pro")
        }
    }
}

رائع

android {
    buildTypes {
        release {
            minifyEnabled true
            proguardFiles
                getDefaultProguardFile('proguard-android-optimize.txt'),
                'proguard-rules.pro'
        }
        configureEach {
            consumerProguardFiles "consumer-rules.pro"
        }
    }
}

يُرجى العلم أنّ سلوك proguardFiles يختلف كثيرًا عن consumerProguardFiles:

  • يتم استخدام proguardFiles في وقت الإنشاء، غالبًا مع getDefaultProguardFile("proguard-android-optimize.txt")، لتحديد الجزء من مكتبتك الذي يجب الاحتفاظ به أثناء إنشاء المكتبة. على الأقل، يجب أن يكون هذا هو واجهة برمجة التطبيقات المتاحة للجميع.
  • في المقابل، يتم تجميع consumerProguardFiles في المكتبة لتحديد التحسينات التي يتم إجراؤها لاحقًا أثناء إنشاء تطبيق يستخدِم مكتبتك.

على سبيل المثال، إذا كانت مكتبتك تستخدِم ميزة "العرض المرجعي" لإنشاء فئات داخلية، قد تحتاج إلى تحديد قواعد الاحتفاظ في كلّ من proguardFiles و consumerProguardFiles.

إذا كنت تستخدم -repackageclasses في إصدار مكتبتك، أعِد تجميع الفصول الدراسية في حزمة فرعية داخل حزمة مكتبتك. على سبيل المثال، استخدِم -repackageclasses 'com.example.mylibrary.internal' بدلاً من -repackageclasses 'internal'.

إتاحة برامج تصغير مختلفة (ميزة متقدمة)

يمكنك تخصيص القواعد لاستهداف برامج تصغير معيّنة (R8 أو ProGuard)، بالإضافة إلى إصدارات معيّنة من برامج التصغير. يتيح ذلك لمكتبتك العمل على النحو الأمثل في المشاريع التي تستخدم إصدارات جديدة من أداة تصغير الفيديو، مع السماح بمواصلة استخدام القواعد الحالية في المشاريع التي تستخدم إصدارات قديمة من أداة تصغير الفيديو.

لتحديد قواعد التصغير المستهدَفة، عليك تضمينها في مواضع محدّدة داخل مكتبة AAR أو JAR، كما هو موضّح أدناه.

In an AAR library:
    consumer-proguard-rules.pro (legacy location)
    classes.jar
    └── META-INF
        └── com.android.tools (targeted shrink rules location)
            ├── r8-from-<X>-upto-<Y>/<R8-rules-file>
            └── proguard-from-<X>-upto-<Y>/<ProGuard-rules-file>

In a JAR library:
    META-INF
    ├── proguard/<ProGuard-rules-file> (legacy location)
    └── com.android.tools (targeted shrink rules location)
        ├── r8-from-<X>-upto-<Y>/<R8-rules-file>
        └── proguard-from-<X>-upto-<Y>/<ProGuard-rules-file>

وهذا يعني أنّ قواعد التصغير المستهدفة يتم تخزينها في الدليل META-INF/com.android.tools لملف JAR أو في الدليل META-INF/com.android.tools داخل classes.jar لملف AAR.

ضمن هذا الدليل، يمكن أن يكون هناك عدة أدلة بأسماء على شكل r8-from-<X>-upto-<Y> أو proguard-from-<X>-upto-<Y> للإشارة إلى إصدارات برامج التصغير التي تم كتابة القواعد داخل الأدلة لها. يُرجى العِلم أنّ الجزءَين -from-<X> و-upto-<Y> اختياريان، وأنّ الإصدار <Y> حصري، ويجب أن تكون نطاقات الإصدارات مستمرة.

على سبيل المثال، يشكّل r8-upto-8.0.0, r8-from-8.0.0-upto-8.2.0 وr8-from-8.2.0 مجموعة صالحة من قواعد التصغير المستهدفة. ستستخدم R8 القواعد ضمن الدليل r8-from-8.0.0-upto-8.2.0 من الإصدار 8.0.0 إلى الإصدار 8.2.0، ولكن بدون تضمين الإصدار 8.2.0.

استنادًا إلى هذه المعلومات، يختار المكوّن الإضافي لنظام Gradle المتوافق مع Android القواعد من ملفّات ملفّات الدليل R8 المطابقة. إذا لم تحدّد المكتبة قواعد تصغير مستهدفة، سيختار المكوّن الإضافي لنظام Android Gradle القواعد من المواقع الجغرافية القديمة (proguard.txt لملف AAR أو META-INF/proguard/<ProGuard-rules-file> لملف JAR).