שימוש בכלים לבדיקת קוד, כמו lint, יכול לעזור לכם למצוא בעיות ולשפר את הקוד, אבל כלים לבדיקה יכולים להסיק רק עד גבול מסוים. מזהי משאבים של Android,
לדוגמה, שימוש ב-int כדי לזהות מחרוזות, גרפיקה, צבעים וסוגי משאבים אחרים,
כך שכלי בדיקה לא יכולים לזהות אם ציינתם משאב מחרוזת במקום שבו הייתם צריכים
לציין צבע. במצב כזה, יכול להיות שהאפליקציה לא תעובד כמו שצריך או לא תפעל בכלל, גם אם אתם משתמשים בבדיקת קוד.
הערות מאפשרות לכם לספק רמזים לכלי בדיקת קוד, כמו lint, כדי לעזור לזהות את הבעיות העדינות יותר בקוד. ההערות מתווספות כתגי מטא-נתונים שמצרפים למשתנים, לפרמטרים ולערכים מוחזרים כדי לבדוק ערכים מוחזרים של שיטות, פרמטרים שהועברו, משתנים מקומיים ושדות. כשמשתמשים בהערות עם כלים לבדיקת קוד, הן יכולות לעזור לכם לזהות בעיות כמו חריגות מצביע null וסוגי משאבים מתנגשים.
ב-Android יש תמיכה במגוון הערות דרך ספריית ההערות של Jetpack.
אפשר לגשת לספרייה דרך החבילה androidx.annotation.
הערה: אם מודול תלוי במעבד אנוטציות, צריך להשתמש בהגדרת התלות kapt או ksp ל-Kotlin, או בהגדרת התלות annotationProcessor ל-Java כדי להוסיף את התלות הזו.
הוספת הערות לפרויקט
כדי להפעיל הערות בפרויקט, מוסיפים את התלות androidx.annotation:annotation לספרייה או לאפליקציה. כל ההערות שמוסיפים נבדקות כשמריצים בדיקת קוד או משימת lint.
הוספת התלות של ספריית Jetpack Annotations
ספריית Jetpack Annotations מתפרסמת במאגר Maven של Google.
כדי להוסיף את ספריית ההערות של Jetpack לפרויקט, מוסיפים את השורה הבאה לבלוק dependencies בקובץ build.gradle או build.gradle.kts:
Kotlin
dependencies { implementation("androidx.annotation:annotation:1.11.0") }
מגניב
dependencies { implementation 'androidx.annotation:annotation:1.11.0' }
אם אתם משתמשים בהערות במודול הספרייה שלכם, ההערות נכללות כחלק מקובץ ה-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 באמצעות שורת הפקודה. למרות שזה יכול להיות שימושי לסימון בעיות בשרת אינטגרציה רציפה (CI), המשימה lint לא אוכפת הערות nullness (שמתוארות בקטע הבא). רק Android Studio עושה את זה. למידע נוסף על הפעלה והרצה של בדיקות lint, קראו את המאמר שיפור הקוד באמצעות בדיקות lint.
למרות שקונפליקטים בהערות יוצרים אזהרות, האזהרות האלה לא מונעות את הידור האפליקציה.
הערות Nullness
הערות Nullness יכולות להיות שימושיות בקוד Java כדי לאכוף אם הערכים יכולים להיות null. הן פחות שימושיות בקוד Kotlin, כי ב-Kotlin יש כללים מובנים לגבי ערכים ריקים שנאכפים בזמן הקימפול.מוסיפים הערות @Nullable ו-@NonNull כדי לבדוק אם משתנה, פרמטר או ערך מוחזר מסוימים הם null. ההערה @Nullable מציינת משתנה, פרמטר או ערך מוחזר שיכולים להיות null.
@NonNull מציין משתנה, פרמטר או ערך החזרה שלא יכולים להיות null.
לדוגמה, אם משתנה מקומי שמכיל ערך null מועבר כפרמטר ל-method עם ההערה @NonNull שמצורפת לפרמטר הזה, בניית הקוד יוצרת אזהרה שמציינת התנגשות עם ערך שאינו null. בנוסף, אם מנסים להפנות לתוצאה של שיטה שמסומנת ב-@Nullable בלי לבדוק קודם אם התוצאה היא null, נוצרת אזהרת nullness. צריך להשתמש ב-@Nullable בערך המוחזר של שיטה רק אם כל שימוש בשיטה חייב לעבור בדיקת null באופן מפורש.
בדוגמה הבאה אפשר לראות איך משתמשים במאפיין המציין אם ערך יכול להיות ריק (nullability). הקוד לדוגמה ב-Kotlin לא משתמש בהערה @NonNull כי היא מתווספת באופן אוטומטי לקוד הבייטים שנוצר כשמציינים סוג שלא יכול להיות null. בדוגמה ב-Java, ההערה @NonNull משמשת בפרמטרים context ו-attrs כדי לבדוק שערכי הפרמטרים שהועברו הם לא null. הוא גם בודק שה-method 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 כדי להסיק באופן אוטומטי הערות nullness ולהוסיף אותן לקוד. בניתוח יכולת ההכלה של ערכי null, המערכת סורקת את החוזים בכל ההיררכיות של השיטות בקוד כדי לזהות:
- שיטות קריאה שיכולות להחזיר ערכי null.
- שיטות שלא אמורות להחזיר ערך null.
- משתנים, כמו שדות, משתנים מקומיים ופרמטרים, שיכולים להיות null.
- משתנים, כמו שדות, משתנים מקומיים ופרמטרים, שלא יכולים להכיל ערך null.
לאחר מכן, הניתוח מוסיף באופן אוטומטי את הערות ה-null המתאימות במיקומים שזוהו.
כדי להריץ ניתוח של מאפיין המציין אם ערך יכול להיות ריק (nullability) ב-Android Studio, בוחרים באפשרות Analyze (ניתוח) > Infer Nullity (הסקת ערכי null). Android Studio מוסיף את ההערות @Nullable ו-@NonNull של Android במיקומים שזוהו בקוד. אחרי שמריצים ניתוח של ערכי null, מומלץ לאמת את ההערות שהוזרקו.
הערה: כשמוסיפים הערות nullness, יכול להיות שההשלמה האוטומטית תציע את ההערות
@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, במקום מספר שלם של צבע, לשיטות עם הערות.
הערות בשרשור
הערות ה-Thread בודקות אם מתבצעת קריאה ל-method מסוג ספציפי של Thread. אפשר להשתמש בהערות הבאות לשרשורים:
כלי ה-build מתייחסים להערות @MainThread ו-@UiThread כניתנות להחלפה, כך שאפשר לקרוא לשיטות @UiThread משיטות @MainThread ולהפך. עם זאת, שרשור ממשק המשתמש יכול להיות שונה מהשרשור הראשי, במקרה של אפליקציות מערכת עם כמה תצוגות בשרשורים שונים. לכן, צריך להוסיף הערות ל-methods שמשויכות להיררכיית התצוגות של האפליקציה באמצעות @UiThread, ולהוסיף הערות רק ל-methods שמשויכות למחזור החיים של האפליקציה באמצעות @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 נמצא בטווח מסוים של ערכי נקודה צפה (floating point). בדוגמה הבאה, הפרמטר 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 כדי לאמת את ההרשאות של מבצע הקריאה החוזרת ל-method. כדי לבדוק הרשאה אחת מתוך רשימה של הרשאות חוקיות, משתמשים במאפיין 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) { //... }
כדי להגדיר הרשאות ל-Intent, צריך להוסיף את דרישת ההרשאה לשדה המחרוזת שמגדיר את שם הפעולה של ה-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) משתמשת בהרשאה עקיפה ב-Intent שמועבר לשיטה:
Kotlin
abstract fun startActivity(@RequiresPermission intent: Intent, bundle: Bundle?)
Java
public abstract void startActivity(@RequiresPermission Intent intent, @Nullable Bundle)
כשמשתמשים בהרשאות עקיפות, כלי ה-build מנתחים את זרימת הנתונים כדי לבדוק אם הארגומנט שהועבר ל-method כולל הערות @RequiresPermission. לאחר מכן, הם אוכפים את כל ההערות הקיימות מהפרמטר בשיטה עצמה. בדוגמה של startActivity(Intent), הערות בכיתה Intent גורמות לאזהרות שמתקבלות לגבי שימושים לא חוקיים ב-startActivity(Intent) כש-Intent בלי ההרשאות המתאימות מועבר ל-method, כמו שמוצג באיור 1.
איור 1. האזהרה נוצרה מהערת הרשאות עקיפות ב-method 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 כדי לוודא שהתוצאה או הערך המוחזר של method מסוים נמצאים בשימוש בפועל. במקום להוסיף הערה לכל method שאינה void באמצעות @CheckResult, הוסיפו את ההערה כדי להבהיר את התוצאות של methods שעלולות לבלבל.
לדוגמה, מפתחי Java חדשים חושבים לפעמים בטעות שהפונקציה <String>.trim() מסירה רווחים מהמחרוזת המקורית. הוספת הערה לשיטה באמצעות @CheckResult מסמנת את השימושים ב-<String>.trim() שבהם הגורם שמפעיל את השיטה לא עושה שום דבר עם הערך המוחזר של השיטה.
בדוגמה הבאה, ה-method checkPermissions() מסומן כדי לבדוק אם יש הפניה לערך המוחזר של ה-method. הוא גם מציין את השיטה 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 כדי לוודא שהפעלת method שמבצעת שינוי (override) מפעילה את ההטמעה של ה-method ברמת-העל (super).
בדוגמה הבאה, השיטה 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 מבטיחה שהמחלקה או המתודה עם האנוטציה לא יוסרו כשהקוד יוקטן בזמן ה-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). שניהם מבצעים את אותה בדיקת lint.
הגבלת API
ההערה @RestrictTo מציינת שהגישה ל-API (חבילה, מחלקה או שיטה) שנוספה לו הערה מוגבלת, באופן הבא:
תת-מחלקות
משתמשים בפורמט ההערה @RestrictTo(RestrictTo.Scope.SUBCLASSES) כדי להגביל את הגישה ל-API למחלקות משנה בלבד.
רק מחלקות שמרחיבות את המחלקה עם ההערות יכולות לגשת ל-API הזה. המשתנה protected של Java לא מגביל מספיק, כי הוא מאפשר גישה ממחלקות לא קשורות באותה חבילה. בנוסף, יש מקרים שבהם רוצים להשאיר שיטה public כדי לאפשר גמישות בעתיד, כי אי אפשר להפוך שיטה public שהייתה בעבר protected ובוטלה, אבל רוצים לספק רמז לכך שהמחלקה מיועדת לשימוש בתוך המחלקה או ממחלקות משנה בלבד.
ספריות
משתמשים בפורמט ההערה @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX) כדי להגביל את הגישה ל-API לספריות שלכם בלבד.
רק קוד הספרייה יכול לגשת ל-API עם ההערות. כך אפשר לא רק לארגן את הקוד בהיררכיית חבילות, אלא גם לשתף את הקוד בין קבוצה של ספריות קשורות. האפשרות הזו כבר זמינה בספריות של Jetpack שיש בהן הרבה קוד הטמעה שלא מיועד לשימוש חיצוני, אבל צריך להיות public כדי לשתף אותו בספריות המשלימות השונות של Jetpack.
בדיקה
השתמשו בפורמט ההערה @RestrictTo(RestrictTo.Scope.TESTS) כדי למנוע ממפתחים אחרים לגשת לממשקי ה-API לבדיקה.
רק קוד בדיקה יכול לגשת ל-API עם ההערות. כך מפתחים אחרים לא יוכלו להשתמש בממשקי API לפיתוח שאתם מתכוונים להשתמש בהם למטרות בדיקה בלבד.