1. 程式人生 > >使用Android Support Annotations優化你的程式碼

使用Android Support Annotations優化你的程式碼

Android Support Annotations提供的註解允許你像lint檢查那樣提供一些提示資訊在審查程式碼上,這可以幫助你解決一些難以發現的程式碼問題。

新增依賴

  1. 選擇File > Project Structure
  2. 點選Dependencies標籤
  3. 點選“+”按鈕然後選擇Library dependency那項
  4. 在彈出的選擇框選擇support-annotations然後點選ok

用上面的方法新增的依賴一般都是最新的,然後在build.gradle就會多出一行依賴。

dependencies {
    compile 'com.android.support:support-annotations:23.3.0'
}

Nullness 註解

新增@Nullable和@NonNull註解去檢驗一個給定的變數,引數或者返回的值是否有效。

  • @Nullable 表示一個引數,變數,或方法返回值可以為null

  • @NonNull 表示一個引數,變數,或方法返回值不能為null

例如添加了@NonNull這個註解表示context和attrs這兩個引數不能為空

import android.support.annotation.NonNull;
...

    /** Add support for inflating the <fragment> tag. */
    @NonNull
    @Override
    public View onCreateView(String name, @NonNull Context context,
      @NonNull AttributeSet attrs) {
      ...
} ...

Resource 註解

對Android引用的資源型別驗證,可以用來區分像DrawablesR.string這種同是integer的型別資源。

新增@StringRes註解檢驗resId是否為string的資源id

import android.support.annotation.StringRes;
...
    public abstract void setTitle(@StringRes int resId);
    ...

同類型的註解還有 @DrawableRes, @DimenRes, @ColorRes, 和@InterpolatorRes等等

Thread 註解

如果一個方法需要在特定型別的執行緒中呼叫,就可以新增這些註解幫助程式碼審查。

  • @UiThread

  • @MainThread

  • @WorkerThread

  • @BinderThread

注意: @MainThread 和 @UiThread 是可以互換的,所以被註解方法只允許從這2個註解宣告的執行緒中呼叫。

Value Constraint 註解

使用@IntRange, @FloatRange, 和 @Size 註解檢對傳遞的引數進行驗證。

  • @IntRange 指定一個int的值必須在一個規定範圍內

例如取一個alpha值在0-255之間

public void setAlpha(@IntRange(from=0,to=255) int alpha) { … }
  • @FloatRange 指定一個float的值必須在一個規定範圍內

例如取一個alpha值在0.0-1.0之間

public void setAlpha(@FloatRange(from=0.0, to=1.0) float alpha) {...}
  • @Size 表示被註解的元素必須有一個給定的數量或長度

@Size 註解檢查集合或陣列的數量,以及String的長度。例如一個集合必須要有一個存在的值就使用@Size(min=1)註解去檢查這個集合的是否合法。又比如使用 @Size(2) 註解表示這個陣列必須要包含兩個存在的值。

例子:表示location這個陣列必須要有一個值

int[] location = new int[3];
button.getLocationOnScreen(@Size(min=1) location);

Permission 註解

使用@RequiresPermission註解用來檢驗一個方法的呼叫者是否已經擁有此許可權。對只檢查單個許可權是否為有效許可權,使用anyOf屬性,對檢查一組許可權使用allOf屬性。

@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) {
    ...
}

CheckResults 註解

使用@CheckResults註解檢驗方法的結果或返回值是否有使用。

@CheckResult(suggest="#enforcePermission(String,int,int,String)")
public abstract int checkPermission(@NonNull String permission, int pid, int uid);

CallSuper 註解

使用@CallSuper註解檢驗方法是否呼叫super實現了父類的方法。

@CallSuper
protected void onCreate(Bundle savedInstanceState) {
}

Enumerated 註解

使用@IntDef@StringDef 註解可以使用註解方式代替列舉實現整型或字串的列舉型別,以檢驗其他型別的程式碼引用。

import android.support.annotation.IntDef;
...
public abstract class ActionBar {
    ...
    //Define the list of accepted constants
    @IntDef({NAVIGATION_MODE_STANDARD, NAVIGATION_MODE_LIST, NAVIGATION_MODE_TABS})

    //Tell the compiler not to store annotation data in the .class file
    @Retention(RetentionPolicy.SOURCE)

    //Declare the NavigationMode annotation
    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);

如果模型引數不是定義好的常數之一,那麼在你構建這段程式碼時就會生成一段警告。

如果一個引數或返回值引用一個有效的模式,你也可以定義帶標誌的註解。

import android.support.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 {}

...

如果修飾的引數或返回的值不引用一個有效的模式,那麼在你構建這段程式碼時就會生成一段警告。

總結

註解 解釋
@AnimatorRes 表示該引數、欄位或者函式返回值應該是一個 Animator 型別的資源
@AnimRes 表示該引數、欄位或者函式返回值應該是一個 Anim 型別的資源
@AnyRes 表示該引數、欄位或者函式返回值應該是一個任意型別的資源
@AnyThred 表示被註解的方法可以在任何執行緒中被呼叫
@ArrayRes 表示該引數、欄位或者函式返回值應該是一個 Array 型別的資源
@AttrRes 表示該引數、欄位或者函式返回值應該是一個 attribute 型別的資源
@BinderThread 表示被註解的方法只可以在被繫結的執行緒中被呼叫
@BoolRes 表示該引數、欄位或者函式返回值應該是一個布林型別的資源
@CallSuper 表示任何重寫的方法都必須呼叫父類的這個方法
@CheckResult 表示不能忽視被註解方法的返回值
@ColorInt 表示該引數、欄位或者函式返回值應該是一個顏色值而不是顏色資源引用,例如應該是一個 AARRGGBB 的整數值。
@ColorRes 表示該引數、欄位或者函式返回值應該是一個 color 型別的資源,而不是顏色值。注意和 ColorInt 區別
@DimenRes 表示該引數、欄位或者函式返回值應該是一個 dimension 型別的資源
@Dimension 表示被註解的整形引數,欄位或返回值是一個尺寸型別
@DrawableRes 表示該引數、欄位或者函式返回值應該是一個 drawable 型別的資源
@FloatRange 表示被註解的元素必須是在一個給定範圍的float或double值
@FractionRes 表示該引數、欄位或者函式返回值應該是一個 fraction 型別的資源
@IdRes 表示該引數、欄位或者函式返回值應該是一個資源的 ID 型別
@IntegerRes 表示該引數、欄位或者函式返回值應該是一個整數型別的資源
@IntRange 表示被註解的元素必須是在一個給定範圍的long或int值
@InterpolatorRes 表示該引數、欄位或者函式返回值應該是一個 interpolator 型別的資源
@keep 表示被註解的元素在構建混淆時不會被刪除或縮小欄位,會保持原欄位
@LayoutRes 表示該引數、欄位或者函式返回值應該是一個 layout 佈局檔案型別的資源
@MainThread 表示被註解的方法只能在主執行緒呼叫
@MenuRes 表示該引數、欄位或者函式返回值應該是一個 menu 型別的資源
@NonNull 表示被註解的引數,欄位或返回值不能為空
@Nullable 表示被註解的引數,欄位或返回值可以為空
@PluralsRes 表示該引數、欄位或者函式返回值應該是一個 plurals 型別的資源
@Px 表示這個整形的引數,欄位或返回值是一個畫素尺寸
@RawRes 表示該引數、欄位或者函式返回值應該是一個 raw 型別的資源
@RequiresApi 表示被註解的元素只能在給定的api級別或更高版本上執行
@RequiresPermission 表示被註解的元素需要(或可能需要)一個或多個許可權
@RequiresPermission.Read 指定需要允許讀許可權
@RequiresPermission.Write 指定需要允許寫許可權
@Size 表示被註解的元素必須有一個給定的大小或長度
@StringDef 表示被註解的元素代表一個邏輯型別並且它的值必須是顯示命名的常量
@StringRes 表示該引數、欄位或者函式返回值應該是一個字串型別的資源
@StyleableRes 表示該引數、欄位或者函式返回值應該是一個 styleable 型別的資源
@StyleRes 表示該引數、欄位或者函式返回值應該是一個 style 型別的資源
@TransitionRes 表示該引數、欄位或者函式返回值應該是一個 transition 型別的資源
@UiThread 表示被註解的方法或構造方法只能在UI執行緒呼叫
@VisibleForTesting 主要用到測試方面,用處很少,標誌作用
@WorkerThread 表示被註解的方法或構造方法只能在工作執行緒呼叫
@XmlRes 表示該引數、欄位或者函式返回值應該是一個 XML 型別的資源