تحسين فحص الرمز باستخدام التعليقات التوضيحية

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

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

يتيح Android استخدام مجموعة متنوعة من التعليقات التوضيحية من خلال مكتبة التعليقات التوضيحية في Jetpack يمكنك الوصول إلى المكتبة من خلال androidx.annotation طرد.

ملاحظة: إذا كانت الوحدة تعتمد على معالِج تعليقات توضيحية، يجب استخدام إعدادات التبعية kapt أو ksp للغة Kotlin. أو ضبط التبعية annotationProcessor لـ Java لإضافة ذلك والتبعية.

إضافة تعليقات توضيحية إلى مشروعك

لتفعيل التعليقات التوضيحية في مشروعك، أضِف androidx.annotation:annotation والاعتمادية على مكتبتك أو تطبيقك. يتم التحقق من أي تعليقات توضيحية تضيفها عند تشغيل التعليمة البرمجية الفحص أو مهمة lint.

إضافة تبعية مكتبة التعليقات التوضيحية في Jetpack

تم نشر مكتبة التعليقات التوضيحية في Jetpack على مستودع Maven من Google: لإضافة مكتبة Jetpack Anotations إلى مشروعك، يجب تضمين ما يلي: السطر في المجموعة dependencies من build.gradle أو ملف build.gradle.kts:

Kotlin

dependencies {
    implementation("androidx.annotation:annotation:1.8.1")
}

رائع

dependencies {
    implementation 'androidx.annotation:annotation:1.8.1'
}
وبعد ذلك، انقر على المزامنة الآن في شريط الأدوات أو إشعار المزامنة الذي يظهر.

إذا استخدمت التعليقات التوضيحية في وحدة المكتبة الخاصة بك، فسيتم تضمين التعليقات التوضيحية كجزء من عنصر أرشيف Android (AAR) بتنسيق XML في ملف annotations.zip. إضافة لا تقدم تبعية androidx.annotation أي تبعية لأي مستخدم من مستخدمي المراحل التالية في مكتبتك

ملاحظة: إذا كنت تستخدم مكتبات Jetpack الأخرى، قد لا تحتاج إلى إضافة تبعية androidx.annotation. لأن العديد من الأشخاص تعتمد مكتبات Jetpack على مكتبة التعليقات التوضيحية، وقد يكون بإمكانك الوصول إلى التعليقات التوضيحية.

للحصول على قائمة كاملة بالتعليقات التوضيحية المضمّنة في مستودع Jetpack، يمكنك الاطّلاع على مكتبة التعليقات التوضيحية في Jetpack المرجع أو استخدام ميزة الإكمال التلقائي لعرض الخيارات المتاحة عبارة import androidx.annotation..

إجراء عمليات فحص للرموز البرمجية

لبدء فحص الرمز من "استوديو Android"، والذي يتضمّن التحقّق من صحة التعليقات التوضيحية فحص الوبر التلقائي، حدد تحليل > افحص الرمز البرمجي من القائمة. يعرض "استوديو Android" رسائل التعارضات للإبلاغ عن المشاكل المحتمَلة عندما يتضمّن رمزك مع التعليقات التوضيحية واقتراح حلول ممكنة.

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

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

تعليقات توضيحية فارغة

يمكن أن تكون التعليقات التوضيحية للقيم الخالية مفيدة في رمز Java لفرض ما إذا كان يمكن أن تكون القيم فارغة. وهي أقل فائدة في التعليمات البرمجية Kotlin، حيث تم تضمين قواعد قابلية القيم الفارغة في Kotlin والتي يتم فرضها على وقت التجميع.

إضافة @Nullable @NonNull تعليقات توضيحية للتحقق من عدم جدوى متغير معين أو معلمة أو عرض قيمة معينة. @Nullable يشير التعليق التوضيحي إلى متغير أو معلمة أو عرض قيمة يمكن أن تكون فارغة. تشير @NonNull إلى متغيّر أو مَعلمة أو قيمة معروضة لا يمكن أن تكون فارغة.

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

يوضح المثال التالي قابلية القيم الفارغة عمليًا. لا يستفيد مثال التعليمة البرمجية لـ Kotlin من التعليق التوضيحي @NonNull لأنّه تتم إضافته تلقائيًا إلى رمز البايت الذي تم إنشاؤه عند تحديد نوع غير قابل للقيم الفارغة. يستفيد مثال Java من التعليق التوضيحي @NonNull. في المَعلمتَين context وattrs للتأكّد من أنّ قيم المَعلمات التي تم ضبطها ليست فارغة. يتحقّق أيضًا من أنّ طريقة onCreateView() نفسها لا تعرض قيمة فارغة:

Kotlin

...
    /** Annotation not used because of the safe-call operator(?)**/
    override fun onCreateView(
            name: String?,
            context: Context,
            attrs: AttributeSet
    ): View? {
        ...
    }
...

Java

import androidx.annotation.NonNull;
...
    /** Add support for inflating the <fragment> tag. **/
    @NonNull
    @Override
    public View onCreateView(String name, @NonNull Context context,
      @NonNull AttributeSet attrs) {
      ...
      }
...

تحليل القيم الفارغة

يتيح "استوديو Android" إجراء تحليل القيم الفارغة للاستنتاج تلقائيًا. وإدراج تعليقات توضيحية للعدم في التعليمة البرمجية. عمليات فحص تحليل قابلية القيم الفارغة العقود عبر التسلسلات الهرمية للطريقة في التعليمة البرمجية لاكتشاف:

  • طرق الاتصال التي يمكن أن تعرض قيمة خالية.
  • الطرق التي يجب ألا تعرض قيمة خالية.
  • هي المتغيّرات، مثل الحقول والمتغيّرات المحلية والمَعلمات التي يمكن أن خالية.
  • فالمتغيرات، مثل الحقول والمتغيّرات المحلية والمعلَمات التي لا يمكنها على قيمة فارغة.

ثم يقوم التحليل تلقائيًا بإدراج التعليقات التوضيحية الفارغة المناسبة في المواقع التي تم اكتشافها.

لإجراء تحليل لقابلية القيم الفارغة في "استوديو Android"، اختَر تحليل > استنتاج القيم الفارغة: يُدرج "استوديو Android" التعليقات التوضيحية @Nullable و@NonNull لنظام التشغيل Android في المواقع التي تم اكتشافها في رمزك. بعد تشغيل تحليل فارغ، من الأفضل التحقق من التعليقات التوضيحية التي تم إدخالها.

ملاحظة: عند إضافة تعليقات توضيحية للعدم، قد يكون الإكمال التلقائي اقتراح IntelliJ @Nullable و تعليقات @NotNull التوضيحية بدلاً من التعليقات التوضيحية الفارغة في Android وقد يستورد المكتبة المقابلة تلقائيًا. ومع ذلك، يمكن استخدام Android Studio يبحث مدقق Lint فقط عن التعليقات التوضيحية الفارغة في Android. عند إثبات ملكية التعليقات التوضيحية، فتأكد من أن مشروعك يستخدم التعليقات التوضيحية الفارغة في Android حتى يمكن أن يُعلمك أداة فحص الوبر بشكل صحيح أثناء فحص الرمز.

التعليقات التوضيحية للمراجع

يمكن أن يكون التحقق من أنواع الموارد مفيدًا لأنه يتم تمرير مراجع Android إلى الموارد، مثل الموارد القابلة للرسم والسلسلة، كأعداد صحيحة.

يشير ذلك المصطلح إلى رمز برمجي يتوقع أن تشير إحدى المعلَمات إلى نوع معيّن من الموارد، مثل String. إلى نوع المرجع المتوقع int، ولكنه يشير في الواقع إلى نوع مرجعي مختلف نوع المورد، مثل مورد R.string.

على سبيل المثال، يمكنك إضافة تعليقات @StringRes التوضيحية إلى تحقَّق مما إذا كانت معلَمة المورد تحتوي على مرجع R.string، كما هو موضّح هنا:

Kotlin

abstract fun setTitle(@StringRes resId: Int)

Java

public abstract void setTitle(@StringRes int resId)

أثناء فحص الرمز، ينشئ التعليق التوضيحي تحذيرًا إذا كانت الإحالة باستخدام R.string لا يتم تمريرها في المعلمة.

يمكن أن تكون التعليقات التوضيحية لأنواع الموارد الأخرى، مثل @DrawableRes و@DimenRes و@ColorRes و@InterpolatorRes وتتم إضافتها باستخدام تنسيق التعليقات التوضيحية نفسه ويتم تشغيلها أثناء فحص الرموز.

إذا كانت المعلمة يتيح استخدام أنواع متعددة من الموارد، يمكنك وضع أكثر من تعليق توضيحي واحد لنوع الموارد على . استخدام "@AnyRes" للإشارة إلى أن المعلمة التي تم التعليق عليها يمكن أن تكون أي نوع من موارد R.

على الرغم من أنّه يمكنك استخدام @ColorRes لتحديد أنّ يجب أن تكون معلمة اللون أو عددًا صحيحًا للون (في RRGGBB أو تنسيق AARRGGBB) لم يتم التعرّف عليه كمورد للألوان. يمكنك بدلاً من ذلك استخدام التعليق التوضيحي @ColorInt لتنفيذ ما يلي: إلى أن المعلمة يجب أن تكون عددًا صحيحًا للّون. ستضع أدوات التصميم علامة على أي رمز غير صحيح يمرر معرف مورد لون مثل android.R.color.black، بدلاً من عدد صحيح للون، إلى طرق تتضمن تعليقات توضيحية.

التعليقات التوضيحية لسلاسل المحادثات

تتحقق التعليقات التوضيحية لسلسلة المحادثات مما إذا كان يتم استدعاء طريقة من نوع معين من سلسلة محادثات. سلسلة المحادثات التالية التعليقات التوضيحية متاحة:

تتعامل أدوات التصميم مع @MainThread إنّ تعليقات @UiThread التوضيحية قابلة للتبديل، وبالتالي يمكنك استدعاء @UiThread. من الطرق @MainThread والعكس صحيح. ولكن من الممكن أن تكون واجهة المستخدم أن تكون سلسلة المحادثات مختلفة عن سلسلة التعليمات الرئيسية، في حال كانت تطبيقات النظام ذات طرق عرض متعددة في سلاسل محادثات مختلفة. ولذلك، يجب إضافة تعليقات توضيحية على الطرق المرتبطة بالتسلسل الهرمي لطريقة عرض التطبيق. مع @UiThread وإضافة تعليقات توضيحية إلى الطرق المرتبطة بدورة حياة التطبيق فقط @MainThread

إذا كانت جميع الطرق في إحدى الفئات تتشارك متطلبات سلاسل المحادثات نفسها، يمكنك إضافة سلسلة محادثات واحدة. التعليق التوضيحي إلى الفئة للتحقق من أن جميع الطرق في الفئة يتم استدعاؤها من نفس النوع .

من الاستخدامات الشائعة للتعليقات التوضيحية لسلسلة المحادثات التحقق من صحة تلك الطرق أو الفئات التي تحتوي على تعليقات توضيحية لا يتم استدعاء الدالة @WorkerThread إلا من سلسلة محادثات مناسبة في الخلفية.

التعليقات التوضيحية لقيود القيمة

يمكنك استخدام @IntRange @FloatRange و تعليقات @Size التوضيحية على للتحقق من صحة قيم المعلمات التي تم تمريرها. كل من @IntRange و@FloatRange تكون أكثر فائدة عند تطبيقها على المعاملات التي يُرجح أن يخطئ المستخدمون فيها في النطاق.

يتحقّق التعليق التوضيحي @IntRange من أنّ عددًا صحيحًا أو معلَمة طويلة. ضمن نطاق محدد. يشير المثال التالي إلى أنّ السمة alpha على قيمة عدد صحيح من 0 إلى 255:

Kotlin

fun setAlpha(@IntRange(from = 0, to = 255) alpha: Int) { ... }

Java

public void setAlpha(@IntRange(from=0,to=255) int alpha) { ... }

يتحقّق التعليق التوضيحي @FloatRange مما إذا كانت المَعلمة عائمة أو مزدوجة ضمن نطاق محدد من قيم النقاط العائمة. يشير المثال التالي إلى أنّ يجب أن تحتوي مَعلمة alpha على قيمة عائمة تتراوح بين 0.0 و1.0:

Kotlin

fun setAlpha(@FloatRange(from = 0.0, to = 1.0) alpha: Float) {...}

Java

public void setAlpha(@FloatRange(from=0.0, to=1.0) float alpha) {...}

يتحقّق التعليق التوضيحي @Size من حجم مجموعة أو صفيفة أو طول سلسلة. يمكن استخدام التعليق التوضيحي @Size للتأكّد في الصفات التالية:

  • الحد الأدنى للحجم، مثل @Size(min=2)
  • الحد الأقصى للحجم، مثل @Size(max=2)
  • الحجم الدقيق، مثل @Size(2)
  • رقم يجب أن يكون المقاس من مضاعفاته، مثل @Size(multiple=2)

على سبيل المثال: @Size(min=1) يتحقّق ممّا إذا كانت إحدى المجموعات فارغة أم لا، و@Size(3) يتأكد من أن الصفيفة تحتوي على ثلاث قيم بالضبط.

يشير المثال التالي إلى أنّ يجب أن تحتوي مصفوفة location على عنصر واحد على الأقل:

Kotlin

fun getLocation(button: View, @Size(min=1) location: IntArray) {
    button.getLocationOnScreen(location)
}

Java

void getLocation(View button, @Size(min=1) int[] location) {
    button.getLocationOnScreen(location);
}

التعليقات التوضيحية للأذونات

استخدام @RequiresPermission التعليق التوضيحي للتحقق من أذونات المتصل بطريقة ما. للتحقق من الحصول على إذن واحد من قائمة الأذونات الصالحة، استخدِم السمة anyOf. للتحقق من وجود مجموعة من الأذونات، استخدِم السمة allOf. يوضح المثال التالي setWallpaper() للإشارة إلى أن المتصل بالطريقة يجب أن لديه إذن permission.SET_WALLPAPERS:

Kotlin

@RequiresPermission(Manifest.permission.SET_WALLPAPER)
@Throws(IOException::class)
abstract fun setWallpaper(bitmap: Bitmap)

Java

@RequiresPermission(Manifest.permission.SET_WALLPAPER)
public abstract void setWallpaper(Bitmap bitmap) throws IOException;

يتطلب المثال التالي المتصل بطريقة copyImageFile() الحصول على إذن بالقراءة في وحدة التخزين الخارجية وإذن بالقراءة في الموقع البيانات الوصفية في الصورة المنسوخة:

Kotlin

@RequiresPermission(allOf = [
    Manifest.permission.READ_EXTERNAL_STORAGE,
    Manifest.permission.ACCESS_MEDIA_LOCATION
])
fun copyImageFile(dest: String, source: String) {
    ...
}

Java

@RequiresPermission(allOf = {
    Manifest.permission.READ_EXTERNAL_STORAGE,
    Manifest.permission.ACCESS_MEDIA_LOCATION})
public static final void copyImageFile(String dest, String source) {
    //...
}

بالنسبة إلى الأذونات في عناصر intent، ضع متطلبات الإذن في حقل السلسلة الذي يُحدِّد اسم الإجراء المطلوب:

Kotlin

@RequiresPermission(android.Manifest.permission.BLUETOOTH)
const val ACTION_REQUEST_DISCOVERABLE = "android.bluetooth.adapter.action.REQUEST_DISCOVERABLE"

Java

@RequiresPermission(android.Manifest.permission.BLUETOOTH)
public static final String ACTION_REQUEST_DISCOVERABLE =
            "android.bluetooth.adapter.action.REQUEST_DISCOVERABLE";

للأذونات على موفّري المحتوى الذين يحتاجون إلى أذونات منفصلة للقراءة والكتابة إمكانية الوصول، يجب التفاف كل متطلبات الإذن في @RequiresPermission.Read أو @RequiresPermission.Write التعليق التوضيحي:

Kotlin

@RequiresPermission.Read(RequiresPermission(READ_HISTORY_BOOKMARKS))
@RequiresPermission.Write(RequiresPermission(WRITE_HISTORY_BOOKMARKS))
val BOOKMARKS_URI = Uri.parse("content://browser/bookmarks")

Java

@RequiresPermission.Read(@RequiresPermission(READ_HISTORY_BOOKMARKS))
@RequiresPermission.Write(@RequiresPermission(WRITE_HISTORY_BOOKMARKS))
public static final Uri BOOKMARKS_URI = Uri.parse("content://browser/bookmarks");

الأذونات غير المباشرة

عندما يعتمد أحد الأذونات على القيمة المحددة التي يتم تقديمها إلى معلمة الطريقة، استخدم @RequiresPermission في المعلَمة نفسها بدون إدراج الأذونات المحدّدة. على سبيل المثال، startActivity(Intent) إذنًا غير مباشر للغرض الذي تم تمريره إلى الطريقة:

Kotlin

abstract fun startActivity(@RequiresPermission intent: Intent, bundle: Bundle?)

Java

public abstract void startActivity(@RequiresPermission Intent intent, @Nullable Bundle)

عند استخدام أذونات غير مباشرة، تُجري أدوات الإصدار تحليلاً لتدفق البيانات للتحقق مما إذا كان تحتوي الوسيطة التي تم تمريرها إلى الطريقة على أي تعليقات @RequiresPermission توضيحية. ثم فرض أي تعليقات توضيحية موجودة من المعلمة على الطريقة نفسها. في جلسة المعمل، مثال startActivity(Intent)، تتسبب التعليقات التوضيحية في الفئة Intent في ظهور التحذيرات الناتجة حول الاستخدامات غير الصالحة لـ startActivity(Intent) عند نية الشراء بدون يتم تمرير الأذونات إلى الطريقة، كما هو موضح في الشكل 1.

الشكل 1. التحذير الذي تم إنشاؤه من تحذير غير مباشر التعليق التوضيحي للأذونات على طريقة startActivity(Intent).

تنشئ أدوات التصميم التحذير على startActivity(Intent) من التعليق التوضيحي. في اسم إجراء intent المقابل في فئة Intent:

Kotlin

@RequiresPermission(Manifest.permission.CALL_PHONE)
const val ACTION_CALL = "android.intent.action.CALL"

Java

@RequiresPermission(Manifest.permission.CALL_PHONE)
public static final String ACTION_CALL = "android.intent.action.CALL";

إذا لزم الأمر، يمكنك استبدال @RequiresPermission بـ @RequiresPermission.Read أو @RequiresPermission.Write عند إضافة تعليقات توضيحية معلمة الطريقة. ومع ذلك، بالنسبة إلى الأذونات غير المباشرة، يجب على @RequiresPermission لا يتم استخدامها مع التعليقات التوضيحية لأذونات القراءة أو الكتابة.

التعليقات التوضيحية للقيمة المعروضة

يمكنك استخدام التعليق التوضيحي @CheckResult من أجل التحقق من استخدام نتيجة الطريقة أو القيمة المعروضة بالفعل. بدلاً من إضافة تعليقات توضيحية إلى كل طريقة غير باطلة مع @CheckResult، أضِف التعليق التوضيحي لتوضيح نتائج الطرق التي من المحتمل أن تكون مربكة.

على سبيل المثال، غالبًا ما يعتقد مطورو Java الجدد عن طريق الخطأ أن تزيل الدالة <String>.trim() المسافة البيضاء من السلسلة الأصلية. إضافة تعليقات توضيحية تُستخدم الطريقة المتضمّنة @CheckResult مَعلمة <String>.trim(). حيث لا يفعل المتصل أي شيء بالقيمة التي تعرضها الطريقة.

يوضّح المثال التالي السمة checkPermissions(). للتحقق مما إذا كانت القيمة المعروضة للطريقة المشار إليها بالفعل. ويسمّى أيضًا enforcePermission() كطريقة لاقتراحها على المطور كبديل:

Kotlin

@CheckResult(suggest = "#enforcePermission(String,int,int,String)")
abstract fun checkPermission(permission: String, pid: Int, uid: Int): Int

Java

@CheckResult(suggest="#enforcePermission(String,int,int,String)")
public abstract int checkPermission(@NonNull String permission, int pid, int uid);

تعليقات CallSuper التوضيحية

يمكنك استخدام التعليق التوضيحي @CallSuper من أجل التحقق من أن طريقة الإلغاء تستدعي التنفيذ المتميز للطريقة.

ما يلي: يوضح هذا المثال الطريقة onCreate() لضمان إلغاء أي طريقة عمليات التنفيذ باستدعاء super.onCreate():

Kotlin

@CallSuper
override fun onCreate(savedInstanceState: Bundle?) {
}

Java

@CallSuper
protected void onCreate(Bundle savedInstanceState) {
}

التعليقات التوضيحية Typedef

تتحقق تعليقات Typedef مما إذا كانت هناك معلمة أو قيمة إرجاع أو حقل يشير إلى مجموعة معينة من الثوابت. كما أنها تتيح إكمال التعليمات البرمجية لتقديم الثوابت المسموح بها.

يمكنك استخدام @IntDef و @StringDef تعليقات توضيحية لإنشاء تعليقات توضيحية العددية لمجموعات الأعداد الصحيحة والسلاسل للتحقق من صحة القيم أنواع مراجع التعليمات البرمجية.

تستخدم التعليقات التوضيحية Typedef السمة @interface للإشارة إلى النوع الجديد للتعليقات التوضيحية المعدودة. التعليقات التوضيحية @IntDef و@StringDef بالإضافة إلى @Retention، وإضافة تعليقات توضيحية إلى التعليق التوضيحي الجديد، وتكون ضرورية لتحديد نوع تعداد. يوضِّح التعليق التوضيحي @Retention(RetentionPolicy.SOURCE) المجمِّع. عدم تخزين بيانات التعليقات التوضيحية العددية في ملف .class

يعرض المثال التالي خطوات إنشاء تعليق توضيحي يتحقّق مما إذا كانت القيمة قد تم تمريرها. تشير معلمة الطريقة إلى أحد الثوابت المحددة:

Kotlin

import androidx.annotation.IntDef
//...
// Define the list of accepted constants and declare the NavigationMode annotation.
@Retention(AnnotationRetention.SOURCE)
@IntDef(NAVIGATION_MODE_STANDARD, NAVIGATION_MODE_LIST, NAVIGATION_MODE_TABS)
annotation class NavigationMode

// Declare the constants.
const val NAVIGATION_MODE_STANDARD = 0
const val NAVIGATION_MODE_LIST = 1
const val NAVIGATION_MODE_TABS = 2

abstract class ActionBar {

    // Decorate the target methods with the annotation.
    // Attach the annotation.
    @get:NavigationMode
    @setparam:NavigationMode
    abstract var navigationMode: Int

}

Java

import androidx.annotation.IntDef;
//...
public abstract class ActionBar {
    //...
    // Define the list of accepted constants and declare the NavigationMode annotation.
    @Retention(RetentionPolicy.SOURCE)
    @IntDef({NAVIGATION_MODE_STANDARD, NAVIGATION_MODE_LIST, NAVIGATION_MODE_TABS})
    public @interface NavigationMode {}

    // Declare the constants.
    public static final int NAVIGATION_MODE_STANDARD = 0;
    public static final int NAVIGATION_MODE_LIST = 1;
    public static final int NAVIGATION_MODE_TABS = 2;

    // Decorate the target methods with the annotation.
    @NavigationMode
    public abstract int getNavigationMode();

    // Attach the annotation.
    public abstract void setNavigationMode(@NavigationMode int mode);
}

عند إنشاء هذا الرمز، يتم إنشاء تحذير إذا لم يتم إنشاء معلَمة mode الإشارة إلى أحد الثوابت المحددة (NAVIGATION_MODE_STANDARD، NAVIGATION_MODE_LIST أو NAVIGATION_MODE_TABS).

يمكنك دمج @IntDef و@IntRange للإشارة إلى أنّ يمكن أن يكون العدد الصحيح مجموعة معينة من الثوابت أو قيمة ضمن نطاق.

تفعيل دمج الثوابت باستخدام العلامات

إذا كان بإمكان المستخدمين دمج الثوابت المسموح بها مع علامة (مثل |، & و^ وما إلى ذلك)، يمكنك تعريف تعليق توضيحي flag للتحقّق مما إذا كانت المَعلمة أو القيمة المعروضة تشير إلى نمط صالح.

ينشئ المثال التالي التعليق التوضيحي DisplayOptions مع قائمة من القيم الصالحة DISPLAY_ ثوابت:

Kotlin

import androidx.annotation.IntDef
...

@IntDef(flag = true, value = [
    DISPLAY_USE_LOGO,
    DISPLAY_SHOW_HOME,
    DISPLAY_HOME_AS_UP,
    DISPLAY_SHOW_TITLE,
    DISPLAY_SHOW_CUSTOM
])
@Retention(AnnotationRetention.SOURCE)
annotation class DisplayOptions
...

Java

import androidx.annotation.IntDef;
...

@IntDef(flag=true, value={
        DISPLAY_USE_LOGO,
        DISPLAY_SHOW_HOME,
        DISPLAY_HOME_AS_UP,
        DISPLAY_SHOW_TITLE,
        DISPLAY_SHOW_CUSTOM
})
@Retention(RetentionPolicy.SOURCE)
public @interface DisplayOptions {}

...

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

الاحتفاظ بالتعليق التوضيحي

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

تنبيه: الصفوف والطرق التي تضيف تعليقات توضيحية إليها التي تستخدم "@Keep" دائمًا في حزمة APK لتطبيقك، حتى إذا لم وتشير إلى هذه الفئات والأساليب ضمن منطق تطبيقك.

لإبقاء حجم التطبيق صغيرًا، يُرجى مراعاة ما إذا كان من الضروري الاحتفاظ كل تعليق توضيحي من نوع @Keep في تطبيقك. إذا كنت تستخدم الانعكاس الوصول إلى فئة أو طريقة تتضمن تعليقات توضيحية، واستخدام -if شرطية في قواعد ProGuard، لتحديد الفئة التي تجعل الانعكاس يستدعي.

لمزيد من المعلومات حول كيفية تصغير الرمز وتحديد الرمز الذي لا يجب إزالته، راجِع تقليص حجم تطبيقك وتشويشه وتحسينه.

التعليقات التوضيحية لمستوى ظهور الرمز

استخدم التعليقات التوضيحية التالية للإشارة إلى مستوى رؤية أجزاء معينة من الرمز، مثل الطرق أو الفئات أو الحقول أو الحزم.

إظهار الرمز للاختبار

تشير رسالة الأشكال البيانية @VisibleForTesting أن التعليق التوضيحي يظهر أكثر من اللازم عادةً لجعل قابلة للاختبار. يحتوي هذا التعليق التوضيحي على وسيطة otherwise اختيارية تتيح لك تحديد مستوى رؤية الطريقة إذا لم يكن الأمر ضروريًا مما يجعلها مرئية للاختبار. تستخدم أداة Lint الوسيطة otherwise لفرض مستوى الرؤية المقصود.

في المثال التالي، تكون myMethod() عادةً private، ولكنها package-private للاختبارات. مع VisibleForTesting.PRIVATE تعرض أداة Lint رسالة إذا تم استدعاء هذه الطريقة من خارج السياق الذي يسمح به وصول private، مثل من وحدة تجميع مختلفة.

Kotlin

@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
fun myMethod() {
    ...
}

Java

@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
void myMethod() { ... }

يمكنك أيضًا تحديد @VisibleForTesting(otherwise = VisibleForTesting.NONE). للإشارة إلى أن الطريقة موجودة فقط للاختبار. هذا النموذج مماثل لاستخدام @RestrictTo(TESTS) كلتاهما تقومان بإجراء نفس فحص الوبر.

حظر واجهة برمجة التطبيقات

@RestrictTo يشير التعليق التوضيحي إلى أنّ الوصول إلى واجهة برمجة التطبيقات التي تتضمّن تعليقات توضيحية (الحزمة أو الفئة أو الطريقة) محدود، على النحو التالي:

الفئات الفرعية

استخدِم نموذج التعليق التوضيحي @RestrictTo(RestrictTo.Scope.SUBCLASSES) لتقييد إمكانية وصول واجهة برمجة التطبيقات إلى الفئات الفرعية فقط.

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

المكتبات

استخدِم نموذج التعليق التوضيحي @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX) من أجل تقييد وصول واجهة برمجة التطبيقات إلى مكتباتك فقط.

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

الاختبار

استخدِم نموذج التعليق التوضيحي @RestrictTo(RestrictTo.Scope.TESTS) لمنع الآخرين من الوصول إلى واجهات برمجة التطبيقات للاختبار.

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