Android 常用注解

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_STANDARDNAVIGATION_MODE_LISTNAVIGATION_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ì)添加到通過反射訪問的方法和類中,以阻止編譯器將代碼視為未使用。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 文章來源:Google 使用代碼檢查工具可以幫助您找到問題并改進(jìn)代碼,不過,檢查工具只能推斷這么多信息。例如,An...
    文文太遠(yuǎn)了閱讀 409評(píng)論 0 0
  • 使用注解改進(jìn)代碼檢查[摘抄官網(wǎng)] 使用代碼檢查工具(例如 Lint)可以幫助您找到問題并改進(jìn)代碼,不過,檢查工具只...
    曬雨LL閱讀 576評(píng)論 1 0
  • 眼皮實(shí)在抬不起來,或許因?yàn)閻鄣牟粔蛏畛粒哦潭痰娜?,失戀帶來的痛苦已?jīng)沒有那么強(qiáng)烈了,像往常一樣,我早早起床,收...
    花想容玉行閱讀 317評(píng)論 1 6
  • 今年夏天,雨后,蝸牛格外的多,這是我在雁灘公園撿來的。我把它們跟我唯一的一條小金魚養(yǎng)在了一起,一共十一個(gè),也拍了不...
    月牙兒飛閱讀 417評(píng)論 0 10
  • 1、閱讀的態(tài)度 閱讀者越主動(dòng)、以及運(yùn)用更多的技巧,則閱讀的效果越好。 2、閱讀的目標(biāo) 分兩種:為獲得資訊而讀,為求...
    時(shí)光的小偷閱讀 322評(píng)論 0 1

友情鏈接更多精彩內(nèi)容