Nullness 注解
-
@Nullable注解指示可以為 null 的變量、參數(shù)或返回值。 -
@NonNull則指示不可為 null 的變量、參數(shù)或返回值。
資源注解
-
@StringRes注解,以檢查資源參數(shù)是否包含R.string引用,其他資源類型的注解@DrawableRes、@DimenRes、@ColorRes和@InterpolatorRes,使用@AnyRes能夠指示注解的參數(shù)可為任意類型的 R 資源。
盡管您可以使用 @ColorRes 指定某個(gè)參數(shù)應(yīng)為顏色資源,但是顏色整型(RRGGBB 或 AARRGGBB 格式)無法識(shí)別為顏色資源。請(qǐng)改用 @ColorInt 注解指示某個(gè)參數(shù)必須為顏色整型。構(gòu)建工具會(huì)標(biāo)記不正確代碼,該代碼會(huì)將顏色資源 ID(例如 android.R.color.black)而不是顏色整型傳遞到已注解方法。
常見的Resource Type注解,使用方式都是指定一個(gè)integer的參數(shù)、成員變量、或者方法,檢查對(duì)應(yīng)的資源類型。
-
AnimatorRes:animator資源類型 -
AnimRes:anim資源類型 -
AnyRes:任意資源類型 -
ArrayRes:array資源類型 -
AttrRes:attr資源類型 -
BoolRes:boolean資源類型 -
ColorRes:color資源類型 -
DimenRes:dimen資源類型。 -
DrawableRes:drawable資源類型。 -
FractionRes:fraction資源類型 -
IdRes:id資源類型 -
IntegerRes:integer資源類型 -
InterpolatorRes:interpolator資源類型 -
LayoutRes:layout資源類型 -
MenuRes:menu資源類型 -
PluralsRes:plurals資源類型 -
RawRes:raw資源類型 -
StringRes:string資源類型 -
StyleableRes:styleable資源類型 -
StyleRes:style資源類型 -
TransitionRes:transition資源類型 -
XmlRes:xml資源類型
以上基本上包括了所有的資源類型,但是有時(shí)需要通過RGB顏色整型來設(shè)置顏色值,在這種情況下,你可以使用@ColorInt注解,表示你期望的是一個(gè)代表顏色的整數(shù)值,如果使用不對(duì)同樣也是編譯不通過
線程注解
線程注解可以檢查某個(gè)方法是否從特定類型的線程調(diào)用。支持以下線程注解:
@MainThread@UiThread@WorkerThread@BinderThread@AnyThread
注:構(gòu)建工具會(huì)將 @MainThread 和 @UiThread 注解視為可互換,因此,您可以從 @MainThread 方法調(diào)用 @UiThread 方法,反之亦然。不過,如果系統(tǒng)應(yīng)用在不同線程上帶有多個(gè)視圖,UI 線程可與主線程不同。因此,您應(yīng)使用 @UiThread 標(biāo)注與應(yīng)用的視圖層次結(jié)構(gòu)關(guān)聯(lián)的方法,使用 @MainThread 僅標(biāo)注與應(yīng)用生命周期關(guān)聯(lián)的方法。
值約束注解
使用 @IntRange、@FloatRange 和 @Size 注解可以驗(yàn)證傳遞的參數(shù)的值。在應(yīng)用到用戶可能弄錯(cuò)其范圍的參數(shù)時(shí),@IntRange 和 @FloatRange 都非常有用。
@IntRange 注解可以驗(yàn)證整型或長整型參數(shù)值是否位于指定范圍內(nèi)。下面的示例可以確保 alpha 參數(shù)包含 0 至 255 范圍內(nèi)的整數(shù)值:
public void setAlpha(@IntRange(from=0, to=255) int alpha) {...}
@FloatRange 注解可以檢查浮點(diǎn)或雙整型參數(shù)值是否位于指定的浮點(diǎn)值范圍內(nèi)。下面的示例可以確保 alpha 參數(shù)包含 0.0 至 1.0 的浮點(diǎn)值:
public void setAlpha(@FloatRange(from=0.0, to=1.0) float alpha) {...}
@Size 注解可以檢查集合或數(shù)組的大小,以及字符串的長度。@Size 注解可用于驗(yàn)證以下質(zhì)量:
最小大?。ɡ?@Size(min=2))
最大大小(例如 @Size(max=2))
確切大?。ɡ?@Size(2))
表示大小必須為此倍數(shù)的數(shù)字(例如 @Size(multiple=2))
例如,@Size(min=1) 可以檢查某個(gè)集合是否不為空,@Size(3) 可以驗(yàn)證某個(gè)數(shù)組是否剛好包含三個(gè)值。下面的示例可以確保 location 數(shù)組至少包含一個(gè)元素:
int[] location = new int[3];
button.getLocationOnScreen(@Size(min=1) location);
權(quán)限注解
使用 @RequiresPermission 注解可以驗(yàn)證方法調(diào)用方的權(quán)限。要檢查有效權(quán)限列表中是否存在某個(gè)權(quán)限,請(qǐng)使用 anyOf 屬性。要檢查是否存在一組權(quán)限,請(qǐng)使用 allOf 屬性。下面的示例會(huì)標(biāo)注 setWallpaper() 方法,以確保方法的調(diào)用方擁有 permission.SET_WALLPAPERS 權(quán)限:
@RequiresPermission(Manifest.permission.SET_WALLPAPER)
public abstract void setWallpaper(Bitmap bitmap) throws IOException;
此示例要求 copyFile() 方法的調(diào)用方同時(shí)具有外部存儲(chǔ)空間的讀寫權(quán)限:
@RequiresPermission(allOf = {
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE})
public static final void copyFile(String dest, String source) {
...
}
對(duì)于 intent 權(quán)限,請(qǐng)將權(quán)限要求添加到定義 intent 操作名稱的字符串字段上:
@RequiresPermission(android.Manifest.permission.BLUETOOTH)
public static final String ACTION_REQUEST_DISCOVERABLE =
"android.bluetooth.adapter.action.REQUEST_DISCOVERABLE";
對(duì)于您需要單獨(dú)讀寫權(quán)限的內(nèi)容提供程序的權(quán)限,請(qǐng)?jiān)?@RequiresPermission.Read 或 @RequiresPermission.Write 注解中包含每個(gè)權(quán)限要求:
@RequiresPermission.Read(@RequiresPermission(READ_HISTORY_BOOKMARKS))
@RequiresPermission.Write(@RequiresPermission(WRITE_HISTORY_BOOKMARKS))
public static final Uri BOOKMARKS_URI = Uri.parse("content://browser/bookmarks");
間接權(quán)限
如果權(quán)限依賴于提供給方法參數(shù)的特定值,請(qǐng)對(duì)參數(shù)本身使用 @RequiresPermission,而不用列出具體權(quán)限。例如, startActivity(Intent) 方法會(huì)對(duì)傳遞到方法的 intent 使用間接權(quán)限:
public abstract void startActivity(@RequiresPermission Intent intent, @Nullable Bundle) {...}
在您使用間接權(quán)限時(shí),構(gòu)建工具將執(zhí)行數(shù)據(jù)流分析以檢查傳遞到方法的參數(shù)是否具有任何 @RequiresPermission 注解。隨后,它們會(huì)對(duì)方法本身強(qiáng)制參數(shù)的任何現(xiàn)有注解。在 startActivity(Intent) 示例中,當(dāng)一個(gè)不具有相應(yīng)權(quán)限的 intent 傳遞到方法時(shí),Intent 類中的注解會(huì)針對(duì) startActivity(Intent) 的無效使用生成警告,如圖 1 中所示。
圖 1. startActivity(Intent) 方法上從間接權(quán)限注解生成的警告。
構(gòu)建工具會(huì)在 startActivity(Intent) 上從 Intent 類中相應(yīng) intent 操作名稱的注解生成警告:
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
@RequiresPermission(Manifest.permission.CALL_PHONE)
public static final String ACTION_CALL = "android.intent.action.CALL";
如果需要,在標(biāo)注方法的參數(shù)時(shí),您可以將 @RequiresPermission 替換為 @RequiresPermission.Read 和/或 @RequiresPermission.Write。不過,間接權(quán)限 @RequiresPermission 不應(yīng)與讀取或?qū)懭霗?quán)限注解搭配使用。
返回值注解
使用 @CheckResult 注解可以驗(yàn)證實(shí)際使用的是方法的結(jié)果還是返回值。添加注釋來闡明可能令人困惑的方法的結(jié)果,而不是使用 @CheckResult 標(biāo)注每個(gè)非空方法。例如,新 Java 開發(fā)者經(jīng)常誤認(rèn)為 <String>.trim() 會(huì)移除原始字符串中的空格。使用 @CheckResult 標(biāo)注方法會(huì)在調(diào)用方未對(duì)方法返回值作任何處理的地方標(biāo)記 <String>.trim() 的使用。
下面的示例會(huì)標(biāo)注 checkPermissions() 方法,以確保實(shí)際引用方法的返回值。它還會(huì)將 enforcePermission() 方法指定為要向開發(fā)者建議的替換方法:
@CheckResult(suggest="#enforcePermission(String,int,int,String)")
public abstract int checkPermission(@NonNull String permission, int pid, int uid);
CallSuper 注解
使用 @CallSuper 注解可以驗(yàn)證替換方法是否會(huì)調(diào)用方法的超類實(shí)現(xiàn)。下面的示例會(huì)標(biāo)注 onCreate() 方法,以確保任何替換方法實(shí)現(xiàn)都會(huì)調(diào)用 super.onCreate():
@CallSuper
protected void onCreate(Bundle savedInstanceState) {
}
Typedef 注解
使用 @IntDef 和 @StringDef 注解,以便能夠創(chuàng)建整型和字符串集的枚舉注解來驗(yàn)證其他類型的代碼引用。Typedef 注解可以確保特定參數(shù)、返回值或字段引用特定的常量集。它們還可以完成代碼以自動(dòng)提供允許的常量。
Typedef 注解使用 @interface 聲明新的枚舉注解類型。@IntDef 和 @StringDef 注解以及 @Retention 可以標(biāo)注新注解,并且為定義枚舉的類型所必需。@Retention(RetentionPolicy.SOURCE) 注解可以告知編譯器不將枚舉的注解數(shù)據(jù)存儲(chǔ)在 .class 文件中。
下面的示例說明了創(chuàng)建注解的具體步驟,此注解可以確保作為方法參數(shù)傳遞的值引用一個(gè)定義的常量:
import android.support.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);
}
在您構(gòu)建此代碼時(shí),如果 mode 參數(shù)不引用一個(gè)定義的常量(NAVIGATION_MODE_STANDARD、NAVIGATION_MODE_LIST 或 NAVIGATION_MODE_TABS),則會(huì)生成警告。
您還可以組合 @IntDef 和 @IntRange,以指示整型可以是給定的常量集或某個(gè)范圍內(nèi)的值。
允許將常量與標(biāo)志相結(jié)合
如果用戶可以將允許的常量與標(biāo)志(例如,|、& 和 ^,等等)相結(jié)合,則您可以通過 flag 屬性定義一個(gè)注解,以檢查某個(gè)參數(shù)或返回值是否會(huì)引用有效模式。下面的示例將使用一組有效的 DISPLAY_ 常量創(chuàng)建 DisplayOptions 注解:
@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 {}
在您使用注解標(biāo)志構(gòu)建代碼時(shí),如果經(jīng)過修飾的參數(shù)或返回值不引用有效模式,則將生成警告。
代碼可訪問性注解
使用 @VisibleForTesting 和 @Keep 注解可以表示方法、類或字段的可訪問性。
@VisibleForTesting 注解指示一個(gè)代碼塊的可見性是否高于讓代碼變得可測(cè)試所需要的水平。
@Keep 注解可以確保如果在構(gòu)建時(shí)縮減代碼,標(biāo)注的元素不會(huì)移除。它一般會(huì)添加到通過反射訪問的方法和類中,以阻止編譯器將代碼視為未使用。