المكوّن الإضافي لنظام Gradle المتوافق مع Android (AGP) هو نظام التصميم الرسمي لتطبيقات Android. يتيح لك هذا الإصدار تجميع العديد من الأنواع المختلفة من المصادر وربطها معًا في تطبيق يمكنك تشغيله على جهاز Android أو محاكي.
يحتوي AGP على نقاط إضافة تتيح للمكوّنات الإضافية التحكّم في مدخلات عملية الإنشاء وتوسيع وظائفها من خلال خطوات جديدة يمكن دمجها مع مهام الإنشاء العادية. لم تتضمّن الإصدارات السابقة من AGP واجهات برمجة تطبيقات رسمية مفصولة بوضوح عن التنفيذات الداخلية. بدءًا من الإصدار 7.0، يتضمّن AGP مجموعة من واجهات برمجة التطبيقات الرسمية والمستقرة التي يمكنك الاعتماد عليها .
دورة حياة واجهة برمجة التطبيقات في AGP
يتّبع AGP مراحل نشاط ميزات Gradle لتحديد حالة واجهات برمجة التطبيقات:
- داخلي: غير مخصص للاستخدام العام
- قيد التطوير: متاح للاستخدام العام ولكنّه غير نهائي، ما يعني أنّه قد لا يكون متوافقًا مع الإصدارات السابقة في الإصدار النهائي
- عامة: متاحة للاستخدام العام والثابت
- متوقفة نهائيًا: لم تعُد متاحة، وتم استبدالها بواجهات برمجة تطبيقات جديدة
سياسة الإيقاف النهائي
يتطور AGP نظرًا لإيقاف واجهات برمجة التطبيقات القديمة نهائيًا واستبدالها بواجهات برمجة تطبيقات جديدة وثابتة ولغة جديدة خاصة بالنطاق (DSL). سيشمل هذا التطوّر إصدارات متعددة من AGP، ويمكنك الاطّلاع على مزيد من المعلومات عنه في المخطط الزمني لنقل البيانات من واجهة برمجة التطبيقات AGP/DSL.
عند إيقاف واجهات برمجة تطبيقات AGP نهائيًا، سواءً بسبب عملية نقل البيانات هذه أو غيرها، ستظل متاحة في الإصدار الرئيسي الحالي، ولكن ستُنشئ تحذيرات. ستتم إزالة واجهات برمجة التطبيقات المتوقّفة نهائيًا بالكامل من AGP في الإصدار الكبير التالي. على سبيل المثال، إذا تم إيقاف واجهة برمجة تطبيقات نهائيًا في الإصدار 7.0 من Android Studio، ستظل متاحة في هذا الإصدار وستُنشئ تحذيرات. لن تكون واجهة برمجة التطبيقات هذه متاحة في IDE AGP 8.0.
للاطّلاع على أمثلة على واجهات برمجة التطبيقات الجديدة المستخدَمة في عمليات تخصيص الإصدار الشائعة، يمكنك مراجعة وصفات مكوّنات إضافية لنظام Android Gradle. وتقدّم أمثلة على تخصيصات الإصدار الشائعة. يمكنك أيضًا العثور على مزيد من التفاصيل حول واجهات برمجة التطبيقات الجديدة في مستندات المرجع.
أساسيات إنشاء Gradle
لا يتناول هذا الدليل نظام إنشاء Gradle بالكامل. ومع ذلك، يتناول الدليل الحد الأدنى من المفاهيم اللازمة لمساعدتك في الدمج مع واجهات برمجة التطبيقات، ويضمّ روابط تؤدي إلى مستندات Gradle الرئيسية للاطّلاع على مزيد من المعلومات.
نفترض أنّ لديك معرفة أساسية بكيفية عمل Gradle، بما في ذلك كيفية ضبط المشاريع وتعديل ملفات الإنشاء وتطبيق المكوّنات الإضافية وتنفيذ المهام. للتعرّف على أساسيات Gradle في ما يتعلّق بـ AGP، ننصحك بمراجعة مقالة ضبط عملية المعالجة . للتعرّف على الإطار العام لتخصيص الإضافات في Gradle، اطّلِع على مقالة تطوير إضافات Gradle المخصّصة.
مسرد مصطلحات الأنواع الكسولة في Gradle
يوفّر Gradle عددًا من الأنواع التي تعمل "ببطء" أو تساعد في تأجيل العمليات الحسابية المكثفة أو
Task
الإنشاء إلى المراحل اللاحقة من عملية الإنشاء. تشكّل هذه الأنواع جوهر العديد من واجهات برمجة التطبيقات في IDE وAGP. تتضمّن القائمة التالية أنواع Gradle الرئيسية المُستخدَمة في التنفيذ البطيء، والأساليب الرئيسية لها.
Provider<T>
- توفّر قيمة من النوع
T
(حيث يشير "T" إلى أي نوع)، ويمكن قراءتها أثناء مرحلة التنفيذ باستخدامget()
أو تحويلها إلىProvider<S>
جديد (حيث يشير "S" إلى نوع آخر) باستخدام الطرقmap()
وflatMap()
وzip()
. يُرجى ملاحظة أنّه يجب عدم استدعاءget()
مطلقًا أثناء مرحلة الإعداد.map()
: تقبل دالة lambda وتُنشئProvider
من النوعS
،Provider<S>
. تستخدم وسيطة lambda إلىmap()
القيمةT
وتنتج القيمةS
. لا يتم تنفيذ دالة lambda على الفور. بدلاً من ذلك، يتم تأجيل تنفيذها إلى اللحظة التي يتم فيها استدعاءget()
في السمةProvider<S>
الناتجة، ما يجعل السلسلة بأكملها بطيئة.flatMap()
: تقبل أيضًا دالة LAMBDA وتُنتجProvider<S>
، ولكن دالة LAMBDA تأخذ القيمةT
وتُنتجProvider<S>
(بدلاً من إنتاج القيمةS
مباشرةً). استخدِم flatMap() عندما لا يمكن تحديد S في وقت الإعداد ويمكنك الحصول علىProvider<S>
فقط. من الناحية العملية، إذا استخدمتmap()
وانتهى بك الأمر بنوع نتيجةProvider<Provider<S>>
، يعني ذلك على الأرجح أنّه كان عليك استخدامflatMap()
بدلاً من ذلك.zip()
: يتيح لك هذا الخيار دمج مثيلَين منProvider
لإنشاء قيمة جديدة للسمةProvider
، مع قيمة محسوبة باستخدام دالة تجمع القيم من حالتَي الإدخالProviders
.
Property<T>
- تنفّذ
Provider<T>
، ولذلك فهي توفر أيضًا قيمة من النوعT
. على عكسProvider<T>
التي تكون للقراءة فقط، يمكنك أيضًا ضبط قيمة لملفProperty<T>
. هناك طريقتان لإجراء ذلك:- اضبط قيمة من النوع
T
مباشرةً عند توفّرها، بدون الحاجة إلى عمليات حسابية مؤجلة. - اضبط
Provider<T>
آخر كمصدر لقيمةProperty<T>
. في هذه الحالة، لا يتمّ إنشاء القيمةT
إلّا عند استدعاءProperty.get()
.
- اضبط قيمة من النوع
TaskProvider
- تنفيذ
Provider<Task>
لإنشاءTaskProvider
، استخدِمtasks.register()
وليسtasks.create()
، لضمان إنشاء المثيلات للمهام ببطء فقط عند الحاجة إليها. يمكنك استخدامflatMap()
للوصول إلى نتائجTask
قبل إنشاءTask
، ما قد يكون مفيدًا إذا كنت تريد استخدام النتائج كمدخلات لعملياتTask
أخرى.
إنّ مقدّمي الخدمات وطرق التحويل ضروريان لإعداد مدخلات ومخرَجات المهام بطريقة غير مُشغّلة، أي بدون الحاجة إلى إنشاء جميع المهام مسبقًا وحلّ القيم.
ويحمل مقدّمو الخدمات أيضًا معلومات تتعلق بتبعية المهام. عند إنشاء Provider
من خلال تحويل مخرجات Task
، تصبح Task
تبعية ضمنية لـ Provider
وسيتم إنشاؤها وتنفيذها عند حلّ قيمة Provider
، مثلاً عندما تتطلّب قيمة Task
أخرى ذلك.
في ما يلي مثال على تسجيل مهمتَين، GitVersionTask
وManifestProducerTask
، مع تأجيل إنشاء المثيلات Task
إلى أن تكون مطلوبة بالفعل. تم ضبط قيمة الإدخال ManifestProducerTask
على Provider
الذي يتم الحصول عليه من ناتج GitVersionTask
، لذا يعتمد ManifestProducerTask
ضمنيًا على GitVersionTask
.
// Register a task lazily to get its TaskProvider.
val gitVersionProvider: TaskProvider =
project.tasks.register("gitVersionProvider", GitVersionTask::class.java) {
it.gitVersionOutputFile.set(
File(project.buildDir, "intermediates/gitVersionProvider/output")
)
}
...
/**
* Register another task in the configuration block (also executed lazily,
* only if the task is required).
*/
val manifestProducer =
project.tasks.register(variant.name + "ManifestProducer", ManifestProducerTask::class.java) {
/**
* Connect this task's input (gitInfoFile) to the output of
* gitVersionProvider.
*/
it.gitInfoFile.set(gitVersionProvider.flatMap(GitVersionTask::gitVersionOutputFile))
}
ولن يتم تنفيذ هاتين المهمتَين إلا إذا تم طلبهما صراحةً. يمكن أن يحدث ذلك
كجزء من طلب Gradle، على سبيل المثال، إذا كنت تُشغّل ./gradlew
debugManifestProducer
، أو إذا كان ناتج ManifestProducerTask
مرتبطًا
ببعض المهام الأخرى وأصبحت قيمته مطلوبة.
بينما ستكتب مهام مخصصة تستهلك مدخلات و/أو تنتج مخرجات، فإن AGP لا يتيح الوصول العام إلى مهامه الخاصة بشكل مباشر. وهي أحد تفاصيل التنفيذ التي تخضع للتغيير من إصدار إلى آخر. بدلاً من ذلك، يوفّر AGP واجهة برمجة التطبيقات Variant API والوصول إلى نتائج مهامه، أو إنشاء عناصر، يمكنك قراءتها وتحويلها. اطّلِع على Variant API والعناصر والمهام في هذا الوثيقة للحصول على مزيد من المعلومات.
مراحل إنشاء Gradle
إنّ إنشاء مشروع هو عملية معقدة وتتطلّب الكثير من الموارد، وهناك ميزات مختلفة، مثل تجنُّب ضبط المهام، والتحققات المُحدَّثة، وميزة التخزين المؤقت للإعدادات، تساعد في تقليل الوقت الذي يتم قضاؤه في العمليات الحسابية التي يمكن إعادة إنتاجها أو غير الضرورية.
لتطبيق بعض عمليات التحسين هذه، يجب أن تمتثل النصوص البرمجية والإضافات في Gradle للقواعد الصارمة خلال كل مرحلة من مراحل إنشاء Gradle المميزة: الإعداد والضبط والتنفيذ. في هذا الدليل، سنركّز على مرحلتَي الإعداد والتنفيذ. يمكنك العثور على مزيد من المعلومات حول كل مراحل عملية الإنشاء في دليل دورة حياة إنشاء Gradle.
مرحلة الضبط
أثناء مرحلة الضبط، يتم تقييم النصوص البرمجية للإصدار لجميع المشاريع التي تُعد جزءًا من الإصدار، ويتم تطبيق المكوّنات الإضافية، ويتم حل تبعيات الإصدار. يجب استخدام هذه المرحلة لإعداد عملية الإنشاء باستخدام كائنات DSL وتسجيل المهام وإدخالاتها بشكل كسول.
ولأنّ مرحلة الإعداد يتم تنفيذها دائمًا، بغض النظر عن المهمة التي يتم طلب تنفيذها، من المهم بشكل خاص إبقاءها بسيطة ومنع أي عمليات حسابية من الاعتماد على مدخلات غير نصوص البناء نفسها.
وهذا يعني أنّه يجب عدم تنفيذ برامج خارجية أو القراءة من الشبكة، أو إجراء عمليات حسابية طويلة يمكن تأجيلها إلى مرحلة التنفيذ كمثيلات Task
مناسبة.
مرحلة التنفيذ
في مرحلة التنفيذ، تتم
تنفيذ المهام المطلوبة والمهام التابعة لها. على وجه التحديد، يتم تنفيذ methods فئة Task
التي تم وضع علامة @TaskAction
عليها. أثناء تنفيذ المهمة، يُسمح لك بالقراءة من مصادر الإدخال (مثل
الملفات) وحلّ مشاكل مقدّمي الخدمة الكسولين من خلال طلب الرقم Provider<T>.get()
. يؤدي حلّ
موفّري البيانات البطيئين بهذه الطريقة إلى بدء سلسلة من طلبات map()
أو flatMap()
التي تتبع
معلومات الاعتماد على المهام الواردة في الموفّر. يتم تنفيذ المهام
ببطء لتحقيق القيم المطلوبة.
Variant API والعناصر والمهام
واجهة برمجة التطبيقات Variant API هي آلية إضافة في المكوّن الإضافي لنظام Gradle المتوافق مع Android تتيح لك معالجة الخيارات المختلفة، التي يتم ضبطها عادةً باستخدام DSL في ملفات إعداد الإصدار، والتي تؤثر في إصدار Android. تتيح لك واجهة برمجة التطبيقات Variant API أيضًا الوصول إلى العناصر الوسيطة والنهائية التي تم إنشاؤها من خلال عملية المعالجة، مثل ملفات الفئات أو البيان المدمج أو ملفات APK/AAB.
عملية إنشاء تطبيق Android ونقاط التوسيع
عند التفاعل مع AGP، استخدِم نقاط التوسيع المصمّمة خصيصًا بدلاً من تسجيل عمليات الاستدعاء المعتادة لدورة حياة Gradle (مثل afterEvaluate()
) أو
إعداد التبعيات الصريحة Task
. تُعدّ المهام التي أنشأها AGP
تفاصيل التنفيذ ولا يتم عرضها كواجهة برمجة تطبيقات عامة. يجب تجنُّب
محاولة الحصول على نُسخ من عناصر Task
أو تخمين أسماء Task
و
إضافة طلبات استدعاء أو تبعيات إلى عناصر Task
هذه مباشرةً.
يُكمل "أداة تطوير التطبيقات" الخطوات التالية لإنشاء نُسخ Task
وتنفيذها،
وتعمل هذه النُسخ بدورها على إنشاء عناصر التصميم. بعد الخطوات الرئيسية المُتعلّقة بإنشاء ملف تعريف
Variant
، يتمّ استدعاء الدوالّ التي تتيح لك إجراء تغييرات على ملف تعريف
معيّن تمّ إنشاؤه كجزء من عملية إنشاء. من المهمّ ملاحظة أنّ جميع وظائف
الاستدعاء تحدث أثناء مرحلة الضبط
(الموضّحة في هذه الصفحة) ويجب تنفيذها بسرعة، مع تأجيل أيّ عمل معقّد
إلى نُسخ Task
المناسبة أثناء مرحلة التنفيذ بدلاً من ذلك.
- تحليل لغة وصف البيانات: يتم ذلك عند تقييم نصوص البناء، وعند إنشاء
والضبط الخاصين بالخصائص المختلفة لعناصر لغة وصف البيانات في Android من العنصر
android
. يتم أيضًا تسجيل طلبات الاستدعاء في Variant API الموضّحة في الأقسام التالية خلال هذه المرحلة.
finalizeDsl()
: وظيفة استدعاء تتيح لك تغيير عناصر DSL قبل أن يتم قفلها لإنشاء مكوّن (صيغة). يتم إنشاء عناصرVariantBuilder
استنادًا إلى البيانات الواردة في عناصر لغة وصف البيانات (DSL).قفل DSL: تم قفل DSL الآن ولم يعُد من الممكن إجراء تغييرات.
beforeVariants()
: يمكن أن يؤثّر هذا المرجع الخلفي في العناصر التي يتم إنشاؤها، وبعض خصائصها، من خلالVariantBuilder
. لا يزال يسمح بإجراء تعديلات على تدفق الإنشاء والأدوات التي يتم إنتاجها.إنشاء الصيغ: تم الآن الانتهاء من قائمة المكوّنات والعناصر التي سيتم إنشاؤها ولا يمكن تغييرها.
onVariants()
: في هذه الدالة المُعاد الاتصال بها، يمكنك الوصول إلى عناصرVariant
التي تم إنشاؤها ويمكنك ضبط قيم أو مقدّمين لقيمProperty
التي تحتوي عليها، ليتم احتسابها بشكلٍ كسول.قفل الأسعار المتغيرة: تم الآن قفل عناصر الأسعار المتغيرة ولم يعُد بالإمكان إجراء تغييرات عليها.
المهام التي تم إنشاؤها: يتم استخدام عناصر
Variant
وقيمProperty
ل إنشاء نُسخTask
اللازمة لتنفيذ عملية الإنشاء.
يوفّر AGP AndroidComponentsExtension
يتيح تسجيل عمليات معاودة الاتصال في finalizeDsl()
وbeforeVariants()
وonVariants()
.
تتوفّر الإضافة في نصوص إنشاء التطبيق من خلال العنصر androidComponents
:
// This is used only for configuring the Android build through DSL.
android { ... }
// The androidComponents block is separate from the DSL.
androidComponents {
finalizeDsl { extension ->
...
}
}
ومع ذلك، ننصحك بالاحتفاظ بنصوص إنشاء البرامج فقط للإعدادات التعريفية
باستخدام لغة وصف البرامج (DSL) الخاصة بوحدة Android
ونقل أي منطق إلزامي مخصّص إلى buildSrc
أو المكوّنات الإضافية الخارجية. يمكنك أيضًا إلقاء نظرة على buildSrc
نماذج في مستودع GitHub لوصفات Gradle لمعرفة كيفية إنشاء مكوّن إضافي في مشروعك. في ما يلي مثال على تسجيل طلبات إعادة الاتصال من رمز المكوّن الإضافي:
abstract class ExamplePlugin: Plugin<Project> {
override fun apply(project: Project) {
val androidComponents = project.extensions.getByType(AndroidComponentsExtension::class.java)
androidComponents.finalizeDsl { extension ->
...
}
}
}
لنلقِ نظرة فاحصة على وظائف الاستدعاء المتاحة ونوع حالات الاستخدام التي يمكن أن يتيحها المكوّن الإضافي في كل منها:
finalizeDsl(callback: (DslExtensionT) -> Unit)
في هذه الدالة المُعاد الاتصال بها، يمكنك الوصول إلى عناصر DSL التي تم
إنشاؤها وتعديلها من خلال تحليل المعلومات من العنصر android
في ملفات التصميم.
سيتم استخدام عناصر لغة برمجة النصّ المستخدَمة (DSL) هذه لإعداد الصيغ وضبطها في مراحل
لاحقة من عملية الإنشاء. على سبيل المثال، يمكنك إنشاء
إعدادات جديدة أو إلغاء السمات آليًا، ولكن يجب تذكُّر أنّه يجب حلّ
جميع القيم في وقت الإعداد، لذا يجب ألّا تعتمد على أي مدخلات خارجية.
بعد انتهاء تنفيذ معاودة الاتصال هذه، لن تعود كائنات DSL مفيدة،
ويجب عليك التوقف عن حفظ مراجع لها أو تعديل قيمها.
abstract class ExamplePlugin: Plugin<Project> {
override fun apply(project: Project) {
val androidComponents = project.extensions.getByType(AndroidComponentsExtension::class.java)
androidComponents.finalizeDsl { extension ->
extension.buildTypes.create("extra").let {
it.isJniDebuggable = true
}
}
}
}
beforeVariants()
في هذه المرحلة من عملية الإنشاء، يمكنك الوصول إلى عناصر VariantBuilder
التي تحدد الأسعار المتغيرة التي سيتم إنشاؤها وخصائصها. على سبيل المثال،
يمكنك إيقاف بعض الصيغ أو اختباراتها أو تغيير قيمة
خاصية (مثل minSdk
) آليًا لخيار محدّد فقط. على غرار
finalizeDsl()
، يجب حلّ جميع القيم التي تقدّمها في وقت الإعداد وعدم الاعتماد على مدخلات خارجية. يجب عدم تعديل كائنات VariantBuilder
بعد انتهاء تنفيذ استدعاء beforeVariants()
.
androidComponents {
beforeVariants { variantBuilder ->
variantBuilder.minSdk = 23
}
}
يقبل الإجراء beforeVariants()
بشكل اختياري VariantSelector
، والذي يمكنك
الحصول عليه من خلال طريقة selector()
في androidComponentsExtension
. يمكنك
استخدامها لفلترة المكوّنات المشارِكة في طلب الاستدعاء استنادًا إلى
اسمها أو نوع الإصدار أو نكهة المنتج.
androidComponents {
beforeVariants(selector().withName("adfree")) { variantBuilder ->
variantBuilder.minSdk = 23
}
}
onVariants()
عند استدعاء onVariants()
، يتم مسبقًا تحديد جميع العناصر التي سيتم إنشاؤها بواسطة
AGP حتى لا يمكنك إيقافها بعد الآن. ومع ذلك، يمكنك
تعديل بعض القيم المستخدَمة للمهام من خلال ضبطها لسمات
Property
في عناصر Variant
. بما أنّه لن يتم حلّ قيم Property
إلا عند تنفيذ مهام AGP، يمكنك ربطها بأمان
بالموفّرين من خلال مهامك المخصّصة التي ستُجري أي عمليات حسابية مطلوبة، بما في ذلك القراءة من مدخلات خارجية مثل الملفات أو الشبكة.
// onVariants also supports VariantSelectors:
onVariants(selector().withBuildType("release")) { variant ->
// Gather the output when we are in single mode (no multi-apk).
val mainOutput = variant.outputs.single { it.outputType == OutputType.SINGLE }
// Create version code generating task
val versionCodeTask = project.tasks.register("computeVersionCodeFor${variant.name}", VersionCodeTask::class.java) {
it.outputFile.set(project.layout.buildDirectory.file("${variant.name}/versionCode.txt"))
}
/**
* Wire version code from the task output.
* map() will create a lazy provider that:
* 1. Runs just before the consumer(s), ensuring that the producer
* (VersionCodeTask) has run and therefore the file is created.
* 2. Contains task dependency information so that the consumer(s) run after
* the producer.
*/
mainOutput.versionCode.set(versionCodeTask.map { it.outputFile.get().asFile.readText().toInt() })
}
المساهمة في إنشاء المصادر التي تم إنشاؤها
يمكن أن يساهم المكوّن الإضافي في توفير بعض أنواع المصادر التي تم إنشاؤها، مثل:
- رمز التطبيق في الدليل
java
- موارد Android في الدليل
res
- موارد Java
في دليل
resources
- مواد عرض Android في
دليل
assets
للاطّلاع على القائمة الكاملة للمصادر التي يمكنك إضافتها، يُرجى الاطّلاع على Sources API.
يوضّح مقتطف الرمز هذا كيفية إضافة مجلد مصدر مخصّص باسم
${variant.name}
إلى مجموعة مصادر Java باستخدام الدالة addStaticSourceDirectory()
. بعد ذلك، تعالج سلسلة أدوات Android هذا المجلد.
onVariants { variant ->
variant.sources.java?.let { java ->
java.addStaticSourceDirectory("custom/src/kotlin/${variant.name}")
}
}
اطّلِع على وصفة addJavaSource لمزيد من التفاصيل.
يوضّح مقتطف الرمز هذا كيفية إضافة دليل يحتوي على موارد Android
تم إنشاؤه من مهمة مخصّصة إلى مجموعة مصادر res
. وتتشابه العملية مع
أنواع المصادر الأخرى.
onVariants(selector().withBuildType("release")) { variant ->
// Step 1. Register the task.
val resCreationTask =
project.tasks.register<ResCreatorTask>("create${variant.name}Res")
// Step 2. Register the task output to the variant-generated source directory.
variant.sources.res?.addGeneratedSourceDirectory(
resCreationTask,
ResCreatorTask::outputDirectory)
}
...
// Step 3. Define the task.
abstract class ResCreatorTask: DefaultTask() {
@get:OutputFiles
abstract val outputDirectory: DirectoryProperty
@TaskAction
fun taskAction() {
// Step 4. Generate your resources.
...
}
}
اطّلِع على وصفة addCustomAsset لمزيد من التفاصيل.
الوصول إلى العناصر وتعديلها
بالإضافة إلى السماح لك بتعديل الخصائص البسيطة في عناصر Variant
، يحتوي AGP
أيضًا على آلية إضافة تتيح لك قراءة أو تحويل
العناصر الوسيطة والنهائية التي يتم إنشاؤها أثناء عملية التصميم. على سبيل المثال، يمكنك قراءة آخر محتوى ملف AndroidManifest.xml
مدمج في Task
مخصّص لتحليله، أو يمكنك استبدال المحتوى بالكامل بمحتوى ملف بيان تم إنشاؤه باستخدام ملف Task
المخصّص.
يمكنك العثور على قائمة العناصر المتاحة حاليًا في مستندات مرجعي
صف Artifact
. يحتوي كل نوع من أنواع العناصر على خصائص معيّنة من المفيد معرفتها:
عدد القيم الفريدة للسمة
يمثّل عدد القيم الفريدة للسمة Artifact
عدد مثيلاتها من FileSystemLocation
، أو عدد الملفات أو الأدلة من نوع العناصر. يمكنك
الحصول على معلومات حول عدد العناصر في العنصر من خلال التحقّق من فئته الرئيسية: ستكون العناصر التي تتضمّن فئة FileSystemLocation
واحدة فئة فرعية من
Artifact.Single
. أما العناصر التي تحتوي على مثيلات FileSystemLocation
متعدّدة، فستكون
فئة فرعية من Artifact.Multiple
.
نوع واحد FileSystemLocation
يمكنك التحقّق مما إذا كان العنصر Artifact
يمثّل ملفات أو أدلة من خلال الاطّلاع على نوعFileSystemLocation
المُحدَّد بالمَعلمات، والذي يمكن أن يكون إما RegularFile
أو
Directory
.
العمليات المتوافقة
يمكن لكل فئة Artifact
تنفيذ أي من الواجهات التالية للإشارة إلى العمليات التي تتوافق معها:
Transformable
: يسمح باستخدامArtifact
كمدخل لـTask
الذي يُجري عمليات تحويل عشوائية عليه ويُخرج إصدارًا جديدًا منArtifact
.-
Appendable
: لا ينطبق إلا على العناصر التي تشكّل فئات فرعية منArtifact.Multiple
. يعني ذلك أنّه يمكن إلحاقArtifact
، أي أنّه يمكن لTask
مخصّصة إنشاء نُسخ جديدة من هذا النوع منArtifact
والتي ستتم إضافتها إلى القائمة الحالية. -
Replaceable
: لا ينطبق إلا على العناصر التي تشكّل فئات فرعية منArtifact.Single
. يمكن استبدالArtifact
القابلة للاستبدال بمثيل جديد تمامًا، يتم إنتاجه كإخراجTask
.
بالإضافة إلى العمليات الثلاث لتعديل العناصر، يتيح كل عنصر
إجراء get()
(أو getAll()
)
الذي يعرض Provider
يتضمّن الإصدار النهائي من العنصر
(بعد الانتهاء من جميع العمليات التي تم إجراؤها عليه).
يمكن أن تضيف عدة مكونات إضافية أي عدد من العمليات على العناصر إلى مسار الإحالة
من خلال دالة الاستدعاء onVariants()
، وسيضمن AGP ربطها بشكل صحيح
كي يتم تنفيذ جميع المهام في الوقت المناسب وإنشاء العناصر
وتحديثها بشكل صحيح. هذا يعني أنه عندما تغير العملية أي مخرجات عن طريق إلحاقها أو استبدالها أو تحويلها، سترى العملية التالية النسخة المحدثة من هذه العناصر كمدخلات، وهكذا.
نقطة الدخول إلى عمليات التسجيل هي فئة Artifacts
.
يوضِّح مقتطف الرمز التالي كيف يمكنك الوصول إلى مثيل Artifacts
من سمة على كائن Variant
في استدعاء onVariants()
.
يمكنك بعد ذلك تمرير TaskProvider
المخصّص للحصول على كائن
TaskBasedOperation
(1)، واستخدامه لربط مدخلاته ومخرجاته باستخدام إحدى
طرق wiredWith*
(2).
تعتمد الطريقة الدقيقة التي يجب اختيارها على عدد القيم الفريدة ونوع
FileSystemLocation
الذي تنفّذه Artifact
التي تريد تحويلها.
أخيرًا، يتم تمرير نوع Artifact
إلى طريقة تمثّل عملية
التي تم اختيارها على عنصر *OperationRequest
الذي تحصل عليه في المقابل، على سبيل المثال،
toAppendTo()
أو
toTransform()
أو toCreate()
(3).
androidComponents.onVariants { variant ->
val manifestUpdater = // Custom task that will be used for the transform.
project.tasks.register(variant.name + "ManifestUpdater", ManifestTransformerTask::class.java) {
it.gitInfoFile.set(gitVersionProvider.flatMap(GitVersionTask::gitVersionOutputFile))
}
// (1) Register the TaskProvider w.
val variant.artifacts.use(manifestUpdater)
// (2) Connect the input and output files.
.wiredWithFiles(
ManifestTransformerTask::mergedManifest,
ManifestTransformerTask::updatedManifest)
// (3) Indicate the artifact and operation type.
.toTransform(SingleArtifact.MERGED_MANIFEST)
}
في هذا المثال، السمة MERGED_MANIFEST
هي SingleArtifact
وقيمة RegularFile
. ولهذا السبب، يجب استخدام طريقة wiredWithFiles
التي تقبل مرجع RegularFileProperty
واحد للإدخال وRegularFileProperty
واحد للمخرجات. هناك طرق wiredWith*
أخرى في
فئة TaskBasedOperation
تعمل مع مجموعات أخرى من القيم الفريدة لArtifact
وأنواع FileSystemLocation
.
للاطّلاع على مزيد من المعلومات عن توسيع نطاق استخدام AGP، ننصحك بقراءة الأقسام التالية من دليل نظام إنشاء Gradle:
- تطوير مكوّنات Gradle الإضافية المخصّصة
- تنفيذ مكوّنات Gradle الإضافية
- تطوير أنواع مهام Gradle المخصّصة
- الإعداد غير المُفعَّل
- تجنُّب ضبط المهام