Android注解:Android 常用注解
- 1 添加支援注解庫依賴項
- 2 運作代碼檢查
- 3 Android常用注解
-
- 3.1 Nullness 注解
-
- 3.1.1 Nullness 分析
- 3.2資源注解
- 3.3 線程注解
- 3.4 值限制注解
- 3.5 權限注解
-
- 間接權限
- 3.6 CallSuper 注解
- 3.7 Typedef 注解
-
- 允許将常量與标志相結合
- 3.8 可通路性注解
首先說一下在Android代碼中使用注解的好處。使用注解向 Lint 之類的代碼檢查工具提供提示,幫助檢測這些更細微的代碼問題;還可以少寫一些重複代碼;使用注解還非常的友善等等。
1 添加支援注解庫依賴項
支援注解庫是 Android 支援庫的一部分。要向您的項目添加注解,您必須下載下傳支援存儲庫并向 build.gradle 檔案中添加 support-annotations 依賴項。
打開 SDK 管理器,方法是點選工具欄中的 SDK Manager 或者選擇 Tools > Android > SDK Manager。
點選 SDK Tools 标簽。
展開 Support Repository 并選中 Android Support Repository 複選框。
點選 OK。
繼續安裝向導的說明操作,安裝軟體包。
- 将以下代碼行添加到 build.gradle 檔案的 dependencies 塊中,向您的項目添加 support-annotations 依賴項:
dependencies { compile 'com.android.support:support-annotations:24.2.0' }
如果下載下傳的庫版本可能較高,是以,確定在此指定的值與第 3 步中的版本比對。
在顯示的工具欄或同步通知中,點選 Sync Now。
2 運作代碼檢查
要從 Android Studio 啟動代碼檢查(包含驗證注解和自動 Lint 檢查),請從菜單欄中選擇 Analyze > Inspect Code。Android Studio 将顯示沖突消息,在您的代碼與注解沖突的地方标記潛在問題并建議可能的解決方法。
3 Android常用注解
3.1 Nullness 注解
Nullness注解包括
@Nullable @NonNull
注解,以檢查變量、參數或者傳回值的nullness。
@Nullness
表示可以為null;
@NonNull
表示不可以為null
通過
@Nullable
标記的方法,如果使用其傳回值不進行null的檢查,則會出現警告。
@Nullable
public TextView getTextView(){
return new TextView(this);
}
//使用
getTextView().setVisibility(View.VISIBLE);
在Android Studio中會報警告:Method invocation “setVisibility” may produce ‘java.lang.NullPointerException’…
3.1.1 Nullness 分析
Android Studio 支援通過運作 nullability分析,在您的代碼中自動推斷和插入 nullness注解。Nullability分析會在您代碼的整個方法層次結構中掃描協定類,以檢測:
- 可傳回 Null 的調用方法
- 不會傳回 Null 的方法
- 可以為 Null 的變量,如字段、局部變量和參數
- 不能為 Null 值的變量,如字段、局部變量和參數
然後,此分析将自動在已檢測到的位置插入相應的 null 注解。
要在 Android Studio 中運作 nullability 分析,請選擇 Analyze > Infer Nullity。Android Studio 會在代碼中已檢測到的位置插入 Android @Nullable 和 @NonNull 注解。運作 null 分析後,最好驗證一下插入的這些注解。
3.2資源注解
驗證資源類型可能非常有用,因為Android對資源(例如可繪制對象和字元串資源)的引用以整型形式傳遞。需要參數來引用特定類型資源(例如可繪制對象)的代碼可以作為預計的引用類型 int 傳入,不過實際将引用不同類型的資源,例如 R.string 資源。
例如,添加 @StringRes 注解,以檢查資源參數是否包含 R.string 引用,如下面所示:
在代碼檢查期間,如果參數中未傳入 R.string 引用,注解将生成警告。
常見的資源注解:
@IntegerRes:R.integer 類型資源。
@AnimatorRes:R.animator 類型資源。
@AnimRes:R.anim 類型資源。
@ArrayRes:R.array 類型資源。
@AttrRes:R.attr 類型資源。
@BoolRes:R.bool 類型資源。
@ColorRes:R.color 類型資源。
@DimenRes:R.dimen 類型資源。
@DrawableRes:R.drawable 類型資源。
@FractionRes:R.fraction 類型資源。(百分比)
@IdRes:R.id 類型資源。
@InterpolatorRes:R.interpolator 類型資源。(插值器)
@LayoutRes:R.layout 類型資源。
@MenuRes:R.menu 類型資源。
@PluralsRes:R.plurals 類型資源。(複數)
@RawRes:R.raw 類型資源。
@StyleableRes:R.styleable 類型資源。
@StyleRes:R.style 類型資源。
@TransitionRes: R.transition 類型資源。
@XmlRes:R.xml 類型資源。
@AnyRes:未知資源。(表示自己不知道是什麼類型的資源。比如有可能為 R.drawable 也有可能是 R.string。)
可以使用相同的注解格式添加并在代碼檢查期間運作。如果您的參數支援多種資源類型,您可以在給定參數上添加更多注解。
@AnyRes 能夠訓示注解的參數可為任意類型的 R 資源。
@ColorRes 與@ColorInt
盡管您可以使用 @ColorRes 指定某個參數應為顔色資源,但是顔色整型(RRGGBB 或 AARRGGBB 格式)無法識别為顔色資源。請改用 @ColorInt 注解訓示某個參數必須為顔色整型。建構工具會标記不正确代碼,該代碼會将顔色資源 ID(例如 android.R.color.black)而不是顔色整型傳遞到已注解方法。
3.3 線程注解
線程注解可以檢查某個方法是否從特定類型的線程調用。支援以下線程注解
- @MainThread
- @UiThread
- @WorkerThread
- @BinderThread
- @AnyThread
注:1、建構工具會将 @MainThread 和 @UiThread 注解視為可互換,是以,您可以從 @MainThread 方法調用 @UiThread 方法,反之亦然。不過,如果系統應用在不同線程上帶有多個視圖,UI 線程可與主線程不同。是以,您應使用 @UiThread 标注與應用的視圖層次結構關聯的方法,使用 @MainThread 僅标注與應用生命周期關聯的方法。
2、WorkerThread 表示标記的方法隻應該在工作線程上調用。如果标記的是一個類,那麼該類中的所有方法都應是在一個工作線程上調用
3、BinderThread 表示标記的方法隻應在綁定線程上調用。如果标記的是一個類,那麼該類中的所有方法都應是在綁定線程被調用
3.4 值限制注解
使用 @IntRange、@FloatRange 和 @Size 注解可以驗證傳遞的參數的值。在應用到使用者可能弄錯其範圍的參數時,@IntRange 和 @FloatRange 都非常有用。
例:
public void setAlpha(@IntRange(from=0,to=255) int alpha) { … }
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))
int[] location = new int[3];
button.getLocationOnScreen(@Size(min=1) location);
3.5 權限注解
使用 @RequiresPermission 注解可以驗證方法調用方的權限。
@RequiresPermission(Manifest.permission.SET_WALLPAPER)
public abstract void setWallpaper(Bitmap bitmap) throws IOException;
@RequiresPermission(allOf = {
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE})
public static final void copyFile(String dest, String source) {
...
}
要檢查有效權限清單中是否存在某個權限,請使用 anyOf 屬性。要檢查是否存在一組權限,請使用 allOf 屬性。上面的示例會标注 setWallpaper() 方法,以確定方法的調用方擁有 permission.SET_WALLPAPERS 權限;
要求 copyFile() 方法的調用方同時具有外部存儲空間的讀寫權限
對于 intent 權限,請将權限要求添加到定義 intent 操作名稱的字元串字段上:
@RequiresPermission(android.Manifest.permission.BLUETOOTH)
public static final String ACTION_REQUEST_DISCOVERABLE =
"android.bluetooth.adapter.action.REQUEST_DISCOVERABLE";
對于您需要單獨讀寫權限的内容提供程式的權限,請在
@RequiresPermission.Read
或
@RequiresPermission.Write
注解中包含每個權限要求:
@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 使用間接權限:
在您使用間接權限時,建構工具将執行資料流分析以檢查傳遞到方法的參數是否具有任何 @RequiresPermission 注解。随後,它們會對方法本身強制參數的任何現有注解。在 startActivity(Intent) 示例中,當一個不具有相應權限的 intent 傳遞到方法時,Intent 類中的注解會針對 startActivity(Intent) 的無效使用生成警告,如圖 1 中所示。
圖 1. startActivity(Intent) 方法上從間接權限注解生成的警告。
建構工具會在 startActivity(Intent) 上從 Intent 類中相應 intent 操作名稱的注解生成警告:
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
@RequiresPermission(Manifest.permission.CALL_PHONE)
public static final String ACTION_CALL = "android.intent.action.CALL";
如果需要,在标注方法的參數時,您可以将 @RequiresPermission 替換為 @RequiresPermission.Read 和/或 @RequiresPermission.Write。不過,間接權限 @RequiresPermission 不應與讀取或寫入權限注解搭配使用。
3.6 CallSuper 注解
使用 @CallSuper 注解可以驗證替換方法是否會調用方法的超類實作。下面的示例會标注 onCreate() 方法,以確定任何替換方法實作都會調用 super.onCreate():
@CallSuper
protected void onCreate(Bundle savedInstanceState) {
}
3.7 Typedef 注解
使用 @IntDef 和 @StringDef注解,能夠建立整型和字元串集的 枚舉 注解來驗證其他類型的代碼引用。
Typedef 注解可以確定特定參數、傳回值或字段引用特定的常量集。它們還可以完成代碼以自動提供允許的常量。
下面的示例說明了建立注解的具體步驟,此注解可以確定作為方法參數傳遞的值引用一個定義的常量:
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);
在您建構此代碼時,如果 mode 參數不引用一個定義的常量(NAVIGATION_MODE_STANDARD、NAVIGATION_MODE_LIST 或 NAVIGATION_MODE_TABS),則會生成警告。
您還可以組合 @IntDef 和 @IntRange,以訓示整型可以是給定的常量集或某個範圍内的值。
允許将常量與标志相結合
如果使用者可以将允許的常量與标志(例如,|、& 和 ^,等等)相結合,則您可以通過 flag 屬性定義一個注解,以檢查某個參數或傳回值是否會引用有效模式。下面的示例将使用一組有效的 DISPLAY_ 常量建立 DisplayOptions 注解:
import android.support.annotation.IntDef;
...
public static final int DISPLAY_USE_LOGO = 1;
public static final int DISPLAY_SHOW_HOME = 2;
public static final int DISPLAY_HOME_AS_UP= 4;
public static final int DISPLAY_SHOW_TITLE= 8;
public static final int DISPLAY_SHOW_CUSTOM =16;
@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 {}
//使用
@DisplayOptions int a= DISPLAY_USE_LOGO;
@DisplayOptions int b= DISPLAY_SHOW_HOME;
@DisplayOptions int c= a|b;
在您使用注解标志建構代碼時,如果經過修飾的參數或傳回值不引用有效模式,則将生成警告。
3.8 可通路性注解
使用 @VisibleForTesting 和 @Keep 注解可以表示方法、類或字段的可通路性。
@VisibleForTesting 注解訓示一個代碼塊的可見性是否高于讓代碼變得可測試所需要的水準。
@Keep 注解可以確定标記的指定代碼在混淆時不會被混淆。它一般會添加到通過反射通路的方法和類中,以阻止編譯器将代碼視為未使用。
參考資料:
- Android官方注解
- Android 中注解的使用