שיפור בדיקת הקוד בעזרת הערות

שימוש בכלים לבדיקת קוד, כמו lint, יכול לעזור לכם למצוא בעיות ולשפר את הקוד, אבל כלים לבדיקת קוד יכולים להסיק רק עד גבול מסוים. לדוגמה, מזהי המשאבים של Android משתמשים ב-int כדי לזהות מחרוזות, גרפיקה, צבעים וסוגים אחרים של משאבים, כך שכלי הבדיקה לא יכולים לדעת מתי ציינת משאב מחרוזת במקום צבע. המצב הזה עלול לגרום לכך שהאפליקציה תעבור רינדור שגוי או לא תפעל בכלל, גם אם משתמשים בבדיקת הקוד.

הערות מאפשרות לספק רמזים לכלים לבדיקת קוד, כמו lint, כדי לזהות בעיות קוד מתוחכמות יותר. ההערות מתווספות בתור תגי מטא-נתונים שמצרפים למשתנים, לפרמטרים ולערכים המוחזרים כדי לבדוק את ערכי ההחזרה של השיטות, את הפרמטרים המועברים, את המשתנים המקומיים ואת השדות. כשמשתמשים בהערות עם כלים לבדיקת קוד, אפשר לזהות בעיות כמו חריגות של נקודות הצבעה ל-null וקונפליקטים מסוג משאבים.

Android תומך במגוון הערות באמצעות ספריית ההערות של Jetpack. אפשר לגשת לספרייה דרך החבילה androidx.annotation.

הערה: אם למודול יש תלות במעבד הערות, צריך להשתמש בהגדרת התלות kapt או ksp ל-Kotlin, או בהגדרת התלות annotationProcessor ל-Java כדי להוסיף את התלות הזו.

הוספת הערות לפרויקט

כדי להפעיל את ההערות בפרויקט, מוסיפים את התלות androidx.annotation:annotation לספרייה או לאפליקציה. כל ההערות שתוסיפו ייבדקו כשמריצים בדיקת קוד או משימה מסוג lint.

הוספת התלות בספרייה Jetpack Annotations

הספרייה של Jetpack Annotations מתפרסמת ב-Maven Repository של Google. כדי להוסיף את ספריית Jetpack Anotations לפרויקט, צריך לכלול את השורה הבאה בבלוק dependencies בקובץ build.gradle או בקובץ build.gradle.kts:

Kotlin

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

Groovy

dependencies {
    implementation 'androidx.annotation:annotation:1.9.1'
}
לאחר מכן, לוחצים על סנכרון עכשיו בסרגל הכלים או בהתראה על הסנכרון שמופיעה.

אם אתם משתמשים בהערות במודול הספרייה שלכם, ההערות נכללות כחלק מ-artifact של Android Archive ‏ (AAR) בפורמט XML בקובץ annotations.zip. הוספת התלות ב-androidx.annotation לא יוצרת תלות אצל משתמשים בספרייה שלכם במורד הזרם.

הערה: אם אתם משתמשים בספריות אחרות של Jetpack, יכול להיות שלא תצטרכו להוסיף את התלות ב-androidx.annotation. ספריות רבות אחרות של Jetpack תלויות בספריית ההערות, כך שיכול להיות שכבר יש לכם גישה להערות.

רשימה מלאה של ההערות שכלולות במאגר של Jetpack מופיעה במאמר העזרה בנושא ספריית ההערות של Jetpack. אפשר גם להשתמש בתכונת ההשלמה האוטומטית כדי להציג את האפשרויות הזמינות להצהרה import androidx.annotation..

הרצת בדיקות קוד

כדי להתחיל בדיקה של קוד מ-Android Studio, שכוללת אימות של הערות ובדיקת שגיאות אוטומטית, בוחרים באפשרות Analyze > Inspect Code בתפריט. ב-Android Studio מוצגות הודעות על התנגשויות כדי לסמן בעיות פוטנציאליות שבהן הקוד שלכם מתנגש עם הערות, ולהציע פתרונות אפשריים.

אפשר גם לאכוף את ההערות על ידי הרצת המשימה lint באמצעות שורת הפקודה. יכול להיות שזה שימושי לסימון בעיות בשרת של שילוב רצוף, אבל המשימה lint לא אוכפת הערות של ערכים null (מתוארות בקטע הבא). רק Android Studio אוכפת אותן. למידע נוסף על הפעלה וביצוע של בדיקות איתור שגיאות בקוד, ראו שיפור הקוד באמצעות בדיקות איתור שגיאות בקוד.

למרות שהתנגשויות בהערות יוצרות אזהרות, האזהרות האלה לא מונעות את הידור האפליקציה.

הערות על ערכים null

הערות על ערכים null יכולות להיות שימושיות בקוד Java כדי לאכוף אם ערכים יכולים להיות null. הם פחות שימושיים בקוד Kotlin, כי ל-Kotlin יש כללים מובנים של תכונות Nullable, שמופעלים בזמן הידור.

מוסיפים הערות @Nullable ו-@NonNull כדי לבדוק אם משתנה, פרמטר או ערך מוחזר מסוימים הם null. ההערה @Nullable מציינת משתנה, פרמטר או ערך מוחזר שיכולים להיות null. @NonNull מציין משתנה, פרמטר או ערך מוחזר שלא יכול להיות null.

לדוגמה, אם משתנה מקומי שמכיל ערך null מועבר כפרמטר לשיטה עם ההערה @NonNull שמצורפת לפרמטר הזה, ה-build של הקוד יוצר אזהרה לגבי התנגשויות של ערכים שאינם null. בנוסף, ניסיון להפנות לתוצאה של שיטה שמסומנת ב-@Nullable בלי לבדוק קודם אם התוצאה היא null יגרום להצגת אזהרה על nullness. מומלץ להשתמש ב-@Nullable בערך המוחזר של שיטות רק אם צריך לבצע בדיקת null מפורשת בכל שימוש בשיטה.

הדוגמה הבאה ממחישה את האפשרות של ערך null. קוד הדוגמה ב-Kotlin לא משתמש בתיוג @NonNull כי הוא מתווסף באופן אוטומטי לקוד הבייט שנוצר כשמציינים סוג שאינו nullable. בדוגמה ל-Java נעשה שימוש בהערה @NonNull על הפרמטרים context ו-attrs כדי לבדוק שערכי הפרמטרים שהועברו הם לא null. הוא גם בודק שהשיטה onCreateView() עצמה לא מחזירה null:

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 Studio יש תמיכה בהפעלת ניתוח של סטטוס הערך null כדי להסיק באופן אוטומטי ולהוסיף הערות לגבי סטטוס הערך null בקוד. ניתוח של יכולת האיפוס סורק את החוזים לאורך היררכיות השיטות בקוד כדי לזהות:

  • קריאה ל-methods שיכולים להחזיר null.
  • שיטות שלא אמורות להחזיר ערך null.
  • משתנים, כמו שדות, משתנים מקומיים ופרמטרים, שיכולים להיות ערכים null.
  • משתנים, כמו שדות, משתנים מקומיים ופרמטרים, שלא יכולים להכיל ערך null.

לאחר מכן, המערכת תוסיף באופן אוטומטי את ההערות הרלוונטיות של הערך null למיקומים שזוהו.

כדי להריץ ניתוח של יכולת האיפוס ב-Android Studio, בוחרים באפשרות Analyze (ניתוח) > Infer Nullity (הסקת יכולת איפוס). Android Studio מוסיף את ההערות @Nullable ו-@NonNull של Android למיקומים שזוהו בקוד. אחרי שמריצים ניתוח של ערך null, מומלץ לאמת את ההערות שהוזנו.

הערה: כשמוסיפים הערות לגבי ערך null, יכול להיות שהשלמה אוטומטית תציע את ההערות של IntelliJ‏ @Nullable ו-@NotNull במקום את ההערות של Android לגבי ערך null, ויכול להיות שהספרייה המתאימה תיובא באופן אוטומטי. עם זאת, בודק ה-lint של Android Studio מחפש רק את ההערות של null ב-Android. כשמאמתים את ההערות, צריך לוודא שבפרויקט נעשה שימוש בהערות null של Android, כדי שתוכלו לקבל התראות מתאימות במהלך בדיקת הקוד.

הערות על משאבים

אימות סוגי המשאבים יכול להיות שימושי כי הפניות של Android למשאבים, כמו משאבים מסוג drawable ו-string, מועברות כמספרים שלמים.

קוד שמצפה שפרמטר יפנה לסוג ספציפי של משאב, כמו 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 כדי לציין שפרמטר חייב להיות מספר שלם של צבע. כלי ה-build יסמנו קוד שגוי שמעביר מזהה משאב של צבע, כמו android.R.color.black, במקום מספר שלם של צבע, לשיטות עם הערות.

הערות בשרשור

הערות על שרשור בודקות אם שיטה נקראת מסוג ספציפי של שרשור. יש תמיכה בהערות הבאות בשרשור:

כלי ה-build מתייחסים להערות @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 בודקת אם ערך פרמטר מסוג float או double נמצא בטווח מסוים של ערכים של נקודות צפות. בדוגמה הבאה מצוין שהפרמטר alpha חייב להכיל ערך של float בין 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() כדי לציין שלמבצע הקריאה החוזרת (caller) של השיטה צריכה להיות ההרשאה 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;

בדוגמה הבאה, למבצע הקריאה ל-method‏ 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) {
    //...
}

להרשאות של כוונות, צריך להציב את דרישת ההרשאה בשדה המחרוזת שמגדיר את שם הפעולה של הכוונה:

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) משתמשת בהרשאה עקיפה בכוונה (intent) שהועברה לשיטה:

Kotlin

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

Java

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

כשמשתמשים בהרשאות עקיפות, כלי ה-build מבצעים ניתוח של זרימת הנתונים כדי לבדוק אם לארגומנט שהוענק לשיטה יש הערות @RequiresPermission. לאחר מכן, הם אוכפים את כל ההערות הקיימות מהפרמטר בשיטה עצמה. בדוגמה startActivity(Intent), ההערות בכיתה Intent גורמות לאזהרות על שימוש לא חוקי ב-startActivity(Intent) כשמעבירים לשיטה כוונה (intent) ללא ההרשאות המתאימות, כפי שמוצג באיור 1.

איור 1. האזהרה שנוצרה מהערה עקיפה על ההרשאות בשיטה startActivity(Intent).

כלים ל-build יוצרים את האזהרה ב-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 לכל שיטה שאינה void, מוסיפים את ההערה כדי להבהיר את התוצאות של שיטות שעלולות לבלבל.

לדוגמה, מפתחי 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) {
}

הערות של טיפוס נתונים מוגדר מראש

הערות של טיפוס נתונים מותאם אישית בודקות אם פרמטר, ערך מוחזר או שדה מסוימים מפנים לקבוצה ספציפית של קבועים. הם גם מאפשרים להשלמת הקוד להציע באופן אוטומטי את הקבועים המותרים.

אפשר להשתמש בהערות @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 מבטיחה ששיטה או כיתה עם הערה לא יוסרו כשהקוד ימוזער בזמן ה-build. בדרך כלל מוסיפים את ההערה הזו לשיטות ולכיתות שגולשים אליהן באמצעות רפלקציה, כדי למנוע מהמְהדר להתייחס לקוד כאל קוד שלא בשימוש.

זהירות: השיעורים והשיטות שמוסיפים הערות להם באמצעות @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). שתיהן מבצעות את אותה בדיקת איתור שגיאות בקוד.

הגבלת API

ההערה @RestrictTo מציינת שהגישה ל-API (חבילת קוד, סוג או שיטה) עם ההערה מוגבלת באופן הבא:

מחלקות משנה

משתמשים בטופס ההערה @RestrictTo(RestrictTo.Scope.SUBCLASSES) כדי להגביל את הגישה ל-API רק למחלקות משנה.

רק כיתות שמרחיבות את הכיתה עם ההערות יכולות לגשת ל-API הזה. המאפיין protected ב-Java לא מגביל מספיק, כי הוא מאפשר גישה מחלקות לא קשורות באותה חבילה. בנוסף, יש מקרים שבהם רוצים להשאיר שיטה public בגלל גמישות עתידית, כי אי אפשר ליצור שיטה protected קודמת ושיטה public שעברה שינוי, אבל רוצים לספק רמז שהמחלקה מיועדת לשימוש בתוך המחלקה או מתת-מחלקות בלבד.

ספריות

אפשר להשתמש בטופס ההערה @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX) כדי להגביל את הגישה ל-API לספריות שלכם בלבד.

רק לקוד הספרייה שלכם תהיה גישה ל-API עם ההערות. כך תוכלו לא רק לארגן את הקוד בהיררכיית חבילות לפי הצורך, אלא גם לשתף את הקוד בין קבוצה של ספריות קשורות. האפשרות הזו כבר זמינה בספריות של Jetpack שיש בהן הרבה קוד הטמעה שלא מיועד לשימוש חיצוני, אבל צריך להגדיר אותו כ-public כדי לשתף אותו בין הספריות השונות של Jetpack.

בדיקה

משתמשים בטופס ההערה @RestrictTo(RestrictTo.Scope.TESTS) כדי למנוע מפתחים אחרים לגשת לממשקי ה-API לבדיקה.

רק קוד בדיקה יכול לגשת ל-API עם ההערות. כך תוכלו למנוע מפיתוחים אחרים להשתמש ב-API לצורכי פיתוח, אם אתם מתכוונים להשתמש בו למטרות בדיקה בלבד.