المكوّن الإضافي لنظام 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
مرتبطًا
بمهمة أخرى وأصبحت قيمته مطلوبة.
على الرغم من أنّك ستكتب مهام مخصّصة تستهلك مدخلات و/أو تُنتج نتائج، لا توفّر أداة "إدارة الأداء في Google" إمكانية وصول الجميع إلى مهامها مباشرةً. وهي أحد تفاصيل التنفيذ التي تخضع للتغيير من إصدار إلى آخر. بدلاً من ذلك، يوفّر 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 تتيح لك التحكّم في الخيارات المختلفة التي تؤثر في عملية إنشاء حِزم Android، والتي يتم ضبطها عادةً باستخدام DSL في ملفات إعدادات البناء. تتيح لك واجهة برمجة التطبيقات Variant API أيضًا الوصول إلى العناصر الوسيطة والنهائية التي يتم إنشاؤها من خلال عملية المعالجة، مثل ملفات الفئات أو البيان المدمج أو ملفات APK/AAB.
عملية إنشاء تطبيق Android ونقاط التوسيع
عند التفاعل مع AGP، استخدِم نقاط التوسيع المصمّمة خصيصًا بدلاً من تسجيل عمليات الاستدعاء المعتادة لدورة حياة Gradle (مثل afterEvaluate()
) أو
إعداد تبعيات Task
صريحة. تُعدّ المهام التي أنشأها AGP
تفاصيل التنفيذ ولا يتم عرضها كواجهة برمجة تطبيقات عامة. يجب تجنُّب
محاولة الحصول على نُسخ من عناصر Task
أو تخمين أسماء Task
و
إضافة طلبات استدعاء أو تبعيات إلى عناصر Task
هذه مباشرةً.
يُكمِل AGP الخطوات التالية لإنشاء نُسخ 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()
، وسيضمن "أداة تطوير التطبيقات" ربطها بشكل صحيح لكي تتم تنفيذ جميع المهام في الوقت المناسب ويتم إنشاء العناصر وتعديلها بشكل صحيح. وهذا يعني أنّه عندما تغيّر إحدى العمليات أيّ نتائج من خلال إلحاقها أو
استبدالها أو تحويلها، ستظهر العملية التالية الإصدار المعدَّل
من هذه العناصر كإدخالات، وهكذا.
نقطة الدخول إلى عمليات التسجيل هي فئة Artifacts
.
يوضّح المقتطف التالي من الرمز البرمجي كيفية الوصول إلى مثيل من
Artifacts
من خاصيّة في عنصر Variant
في دالة callback الخاصة ب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 مخصّصة
- الإعداد غير المُفعَّل
- تجنُّب ضبط المهام