نظرة عامة على إنشاء Gradle

يتم عادةً إنشاء تطبيقات Android باستخدام نظام الإنشاء Gradle. قبل التعرّف على تفاصيل كيفية ضبط عملية الإنشاء، سنستكشف المفاهيم الأساسية لعملية الإنشاء حتى تتمكّن من فهم النظام بشكل كامل.

ما هو الإصدار؟

يحوّل نظام الإصدار رمز المصدر إلى تطبيق قابل للتنفيذ. تتضمّن عمليات الإنشاء غالبًا أدوات متعدّدة لتحليل تطبيقك أو مكتبتك وتجميعها وربطها وتعبئتها. يستخدم Gradle أسلوبًا مستندًا إلى المهام لتنظيم هذه الأوامر وتنفيذها.

تتضمّن المهام أوامر تحوّل المدخلات إلى مخرجات. تحدّد الإضافات المهام وإعداداتها. يؤدي تطبيق إضافة على عملية الإنشاء إلى تسجيل مهامها وربطها ببعضها البعض باستخدام مدخلاتها ومخرجاتها. على سبيل المثال، سيؤدي تطبيق المكوّن الإضافي لنظام Gradle المتوافق مع Android (AGP) على ملف التصميم إلى تسجيل جميع المهام اللازمة لإنشاء حزمة APK أو مكتبة Android. يتيح لك المكوّن الإضافي java-library إنشاء ملف jar من رمز مصدر Java. تتوفّر مكوّنات إضافية مشابهة للغة Kotlin ولغات أخرى، ولكن المكوّنات الإضافية الأخرى تهدف إلى توسيع نطاق المكوّنات الإضافية. على سبيل المثال، تم تصميم المكوّن الإضافي protobuf لإضافة توافق protobuf إلى المكوّنات الإضافية الحالية، مثل AGP أو java-library.

يُفضّل Gradle الاتفاقية على الضبط، لذا ستتضمّن المكوّنات الإضافية قيمًا تلقائية جيدة فور تثبيتها، ولكن يمكنك ضبط الإصدار بشكل أكبر من خلال لغة خاصة بالمجال (DSL) تعريفية. تم تصميم لغة DSL لتتيح لك تحديد ما تريد إنشاءه، بدلاً من كيفية إنشائه. تتولّى منطق المكوّنات الإضافية إدارة "كيفية" تنفيذ الإجراء. يتم تحديد هذا الإعداد في عدة ملفات إنشاء ضمن مشروعك (والمشاريع الفرعية).

يمكن أن تكون مدخلات المهام ملفات وأدلة بالإضافة إلى معلومات أخرى مشفّرة كأنواع Java (أعداد صحيحة أو سلاسل أو فئات مخصّصة). يمكن أن تكون النواتج عبارة عن دليل أو ملفات فقط لأنّه يجب كتابتها على القرص. يؤدي ربط مخرجات مهمة بمدخلات مهمة أخرى إلى ربط المهام معًا، ما يعني أنّه يجب تنفيذ إحدى المهام قبل الأخرى.

على الرغم من أنّ Gradle يتيح كتابة رموز برمجية عشوائية وتعريفات مهام في ملفات الإنشاء، إلا أنّ ذلك قد يصعّب على الأدوات فهم عملية الإنشاء، كما يصعّب عليك صيانتها. على سبيل المثال، يمكنك كتابة اختبارات للرموز البرمجية داخل المكوّنات الإضافية، ولكن ليس في ملفات الإنشاء. بدلاً من ذلك، عليك حصر منطق التصميم وتعريفات المهام في المكوّنات الإضافية (التي تحدّدها أنت أو شخص آخر) وتحديد طريقة استخدام هذا المنطق في ملفات التصميم.

ماذا يحدث عند تنفيذ إصدار Gradle؟

يتم تنفيذ عمليات إنشاء Gradle على ثلاث مراحل. ينفّذ كل من هذه المراحل أجزاء مختلفة من الرمز الذي تحدّده في ملفات الإصدار.

  • تحدّد عملية التهيئة المشاريع والمشاريع الفرعية التي سيتم تضمينها في عملية الإنشاء، كما تعمل على إعداد مسارات الفئات التي تحتوي على ملفات الإنشاء والمكوّنات الإضافية المستخدَمة. تركّز هذه المرحلة على ملف إعدادات تحدّد فيه المشاريع التي تريد إنشاءها والمواقع التي تريد استرداد المكوّنات الإضافية والمكتبات منها.
  • تسجّل عملية الإعداد مهامًا لكل مشروع، وتنفّذ ملف الإصدار لتطبيق مواصفات الإصدار الخاصة بالمستخدم. من المهم معرفة أنّ رمز الإعداد لن يتمكّن من الوصول إلى البيانات أو الملفات التي تم إنشاؤها أثناء التنفيذ.
  • تنفّذ عملية التنفيذ عملية "إنشاء" تطبيقك الفعلية. يكون الناتج من عملية الإعداد رسمًا بيانيًا موجّهًا بدون دورات (DAG) للمهام، يمثّل جميع خطوات الإنشاء المطلوبة التي طلبها المستخدم (المهام المقدَّمة في سطر الأوامر أو كقيم تلقائية في ملفات الإنشاء). يمثّل هذا الرسم البياني العلاقة بين المهام، سواء كانت العلاقة واضحة في تعريف المهمة أو مستندة إلى مدخلاتها ومخرجاتها. إذا كانت إحدى المهام تتضمّن إدخالاً هو عبارة عن مخرجات مهمة أخرى، يجب تنفيذها بعد المهمة الأخرى. تنفّذ هذه المرحلة المهام القديمة بالترتيب المحدّد في الرسم البياني. وإذا لم تتغيّر مدخلات إحدى المهام منذ آخر تنفيذ لها، سيتخطّاها Gradle.

لمزيد من المعلومات، راجِع دورة حياة الإصدار في Gradle.

لغات DSL للإعداد

يستخدم Gradle لغة خاصة بالنطاق (DSL) لإعداد عمليات الإنشاء. يركّز هذا الأسلوب التصريحي على تحديد البيانات بدلاً من كتابة تعليمات مفصّلة (إلزامية). يمكنك كتابة ملفات الإصدار باستخدام Kotlin أو Groovy، ولكن ننصحك بشدة باستخدام Kotlin.

تحاول لغات DSL تسهيل مشاركة الجميع، سواء خبراء المجال أو المبرمجين، في مشروع ما، وذلك من خلال تحديد لغة صغيرة تمثّل البيانات بطريقة أكثر طبيعية. يمكن أن توسّع مكوّنات Gradle الإضافية لغة DSL من أجل ضبط البيانات التي تحتاج إليها لتنفيذ مهامها.

على سبيل المثال، قد يبدو ضبط جزء Android من الإصدار على النحو التالي:

Kotlin

android {
    namespace = "com.example.app"
    compileSdk {
        version = release(36) {
            minorApiLevel = 1
        }
    }
    // ...

    defaultConfig {
        applicationId = "com.example.app"
        minSdk {
            version = release(23)
        }
        targetSdk {
            version = release(36)
        }
        // ...
    }
}

Groovy

android {
    namespace = 'com.example.app'
    compileSdk {
        version = release(36) {
            minorApiLevel = 1
        }
    }
    // ...

    defaultConfig {
        applicationId = 'com.example.app'
        minSdk {
            version = release(23)
        }
        targetSdk {
            version = release(36)
        }
        // ...
    }
}

في الخلفية، تكون تعليمات DSL البرمجية مشابهة لما يلي:

fun Project.android(configure: ApplicationExtension.() -> Unit) {
    ...
}

interface ApplicationExtension {
    var namespace: String?

    fun compileSdk(configure: CompileSdkSpec.() -> Unit) {
        ...
    }

    val defaultConfig: DefaultConfig

    fun defaultConfig(configure: DefaultConfig.() -> Unit) {
        ...
    }
}

يتم تمثيل كل كتلة في DSL بدالة تأخذ تعبير lambda لضبطها، وسمة تحمل الاسم نفسه للوصول إليها. ويجعل ذلك الرمز البرمجي في ملفات الإنشاء يبدو أشبه بمواصفات البيانات.

المهام التابعة الخارجية

قدّم نظام التصميم Maven مواصفات الاعتمادية ونظام التخزين والإدارة. يتم تخزين المكتبات في مستودعات (خوادم أو أدلة)، مع بيانات وصفية تتضمّن إصدارها وتبعياتها على مكتبات أخرى. تحدّد المستودعات التي تريد البحث فيها وإصدارات التبعيات التي تريد استخدامها، ويقوم نظام الإنشاء بتنزيلها أثناء عملية الإنشاء.

يتم تحديد عناصر Maven Artifacts من خلال اسم المجموعة (الشركة أو المطوّر أو غير ذلك) واسم العنصر (اسم المكتبة) وإصدار هذا العنصر. ويتم تمثيل ذلك عادةً على النحو التالي: group:artifact:version.

يؤدي هذا الأسلوب إلى تحسين إدارة الإصدارات بشكل كبير. غالبًا ما يُطلق على هذه المستودعات اسم "مستودعات Maven"، ولكن الأمر يتعلق بطريقة تجميع ونشر العناصر. وقد تمت إعادة استخدام هذه المستودعات وبيانات التعريف في العديد من أنظمة التصميم، بما في ذلك Gradle (ويمكن لـ Gradle النشر في هذه المستودعات). تتيح المستودعات العامة مشاركة المحتوى ليستخدمه الجميع، بينما تحتفظ مستودعات الشركة بالتبعيات الداخلية داخل الشركة.

يمكنك أيضًا تقسيم مشروعك إلى مشاريع فرعية (تُعرف أيضًا باسم "الوحدات" في "استوديو Android")، والتي يمكن استخدامها أيضًا كعناصر تابعة. ينتج كل مشروع فرعي مخرجات (مثل ملفات JAR) يمكن أن تستهلكها المشاريع الفرعية أو مشروعك ذو المستوى الأعلى. ويمكن أن يؤدي ذلك إلى تحسين وقت الإنشاء من خلال تحديد الأجزاء التي يجب إعادة إنشائها، بالإضافة إلى الفصل بشكل أفضل بين المسؤوليات في التطبيق.

سنشرح بالتفصيل كيفية تحديد الاعتماديات في مقالة إضافة اعتماديات البناء.

تنويعات التصميم

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

تختلف أنواع الإصدارات عن خيارات الإصدار المحدّدة. يُعدِّد "مكوّن Android الإضافي في Gradle" تلقائيًا نوعَي الإصدار "إصدار" و"تصحيح أخطاء"، ولكن يمكنك تعديلهما وإضافة المزيد (ربما للتجربة أو الاختبار الداخلي).

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

يحسِّن إصدار التطبيق التطبيق ويوقّعه باستخدام مفتاح الإصدار ويحمي ملفات التطبيق المثبَّتة.

باستخدام صيغ المنتج، يمكنك تغيير المصدر المضمّن وأنواع التبعيات للتطبيق. على سبيل المثال، قد تحتاج إلى إنشاء إصدارَين من تطبيقك، أحدهما "تجريبي" والآخر "كامل"، أو ربما إصدارَين "مجاني" و "مدفوع". يمكنك كتابة الرمز البرمجي للمصدر المشترك في دليل مجموعة المصادر "الرئيسي"، وتعديل المصدر أو إضافته في مجموعة مصادر تحمل اسم نوع المنتج.

ينشئ "مكوّن Android الإضافي لنظام Gradle" صيغًا لكل مجموعة من نوع الإصدار وصيغة المنتج. في حال عدم تحديد صيغ، سيتم تسمية التنويعات حسب أنواع الإصدارات. في حال تحديد كليهما، سيتم تسمية الصيغة <flavor><Buildtype>. على سبيل المثال، باستخدام نوعَي الإصدار release وdebug، والنكهتَين demo وfull، سينشئ AGP صيغًا على النحو التالي:

  • demoRelease
  • demoDebug
  • fullRelease
  • fullDebug

الخطوات التالية

بعد أن تعرّفت على مفاهيم التصميم، ألقِ نظرة على بنية تصميم Android في مشروعك.