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

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

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

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

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

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

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

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

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

Kotlin

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

מגניב

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

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

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

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

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

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

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

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

הערות לגבי ערכי Null

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

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

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

בדוגמה הבאה אפשר לראות איך אפשר להשתמש בערך null. קוד הדוגמה של Kotlin לא משתמש בהערה @NonNull כי היא מתווספת באופן אוטומטי ל-bytecode שנוצר כשמציינים סוג שאי אפשר להקצות לו ערך null. בדוגמה ל-Java נעשה שימוש בהערה @NonNull בפרמטרים context ו-attrs כדי לבדוק שערכי הפרמטרים שהועברו לא ריקים. היא גם בודקת שהשיטה 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) {
      ...
      }
...

ניתוח של ערכי Null

ב-Android Studio יש תמיכה בהרצת ניתוח של אפשרות קבלת ערך null כדי להסיק באופן אוטומטי ולהוסיף הערות לגבי ערך null בקוד. ניתוח של אפשרות ההחזרה של ערך null סורק את החוזים בהיררכיות של השיטות בקוד כדי לזהות:

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

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

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

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

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

אימות של סוגי משאבים יכול להיות שימושי כי הפניות של 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 מאמתת שערך פרמטר מסוג integer או long נמצא בטווח שצוין. בדוגמה הבאה מצוין שהפרמטר 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;

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

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

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

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

הגבלת API

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

Subclasses

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

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

ספריות

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

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

בדיקה

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

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