前言:
前面學習總結了Java註解的使用,部落格地址詳見Java學習之註解Annotation實現原理,從本質上了解到什麼註解,以及註解怎麼使用?不要看見使用註解就想到反射會影響效能之類,今天我們就來學習一下Android Support Annotations註解來優化我們的程式碼,增加可讀性的同時,也讓讓更多的錯誤消滅在萌芽之中。
Support Annotations簡介:
Android support library從19.1版本開始引入了一個新的註解庫,它包含很多有用的元註解,你能用它們修飾你的程式碼,幫助你發現bug。Support library自己本身也用到了這些註解,所以作為support library的使用者,Android Studio已經基於這些註解校驗了你的程式碼並且標註其中潛在的問題。
Support Annotations如何引入:
註解預設是沒有包含的;它被包裝成一個獨立的庫,如果使用了appcompat庫,那麼Support Annotations就會自動引入進來,因為appcompat使用了Support Annotations,如果沒有則需要在build.gradle中新增如下配置:
dependencies {
compile 'com.android.support:support-annotations:23.4.0'
}
Support Annotations分類:
1.)Nullness註解
@Nullable註解可以用來標識特定的引數或者返回值可以為null。
@NonNull註解可以用來標識引數不能為null。
2.)Resource Type 註解
資源在Android中作為整型值來傳遞。這意味著希望獲取一個drawable作為引數的程式碼很容易被傳遞了一個string型別的資源,因為他們資源id都是整型的,編譯器很難區分。Resource Type註解在這種條件下可以提供型別檢查,例如:
如果型別指定錯誤,編譯不會通過。
常見的Resource Type註解,使用方式都是指定一個integer的引數、成員變數、或者方法,檢查對應的資源型別。
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資源型別
以上基本上包括了所有的資源型別,但是有時需要通過RGB顏色整型來設定顏色值,在這種情況下,你可以使用@ColorInt註解,表示你期望的是一個代表顏色的整數值,如果使用不對同樣也是編譯不通過
3.)Threading 註解
比如我們在專案中處理比較耗時的操作,需要制定在工作子執行緒中執行,可以使用Threading 註解,如果沒有在制定的執行緒中執行也是編譯不過的
幾種Threading註解
- @UiThread UI執行緒
- @MainThread 主執行緒
- @WorkerThread 子執行緒
- @BinderThread 繫結執行緒
4.)Typedef 註解:IntDef/StringDef
整型除了可以作為資源的引用之外,也可以用作“列舉”型別使用。
@IntDef和”typedef”作用非常類似,你可以建立另外一個註解,然後用@IntDef指定一個你期望的整型常量值列表,最後你就可以用這個定義好的註解修飾你的API了。
例如:需要自定義網路型別
private final static int GET=0; private final static int POST=1; private final static int DELETE=2; private final static int PUT=3; @IntDef({GET, POST, DELETE,PUT}) @Retention(RetentionPolicy.SOURCE) public @interface ReqType{}
需要在呼叫時只能傳入指定型別,如果傳入型別不對,編譯不通過
5.)Value Constraints註解:@Size, @IntRange, @FloatRange
在實際開發過程中,我們有時可能需要設定一個取值範圍,這時我們可以使用取值範圍註解來約束。
比如我們設定一個百分比,取值範圍為0-100,
對於資料、集合以及字串,你可以用@Size註解引數來限定集合的大小(當引數是字串的時候,可以限定字串的長度)。
舉幾個例子
- 集合不能為空: @Size(min=1)
- 字串最大隻能有23個字元: @Size(max=23)
- 陣列只能有2個元素: @Size(2)
- 陣列的大小必須是2的倍數 (例如圖形API中獲取位置的x/y座標陣列: @Size(multiple=2)
6.)Permissions 註解: @RequiresPermission
有時我們的方法呼叫需要呼叫者擁有指定的許可權,這時我們可以使用@RequiresPermission註解,
@RequiresPermission(Manifest.permission.SET_WALLPAPER) public abstract void setWallpaper(Bitmap bitmap) throws IOException;
除了上面的單一使用方式,官方同時也給出瞭如下幾種使用場景
(1)如果你至少需要許可權集合中的一個,你可以使用anyOf屬性
@RequiresPermission(anyOf = { Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION}) public abstract Location getLastKnownLocation(String provider);
(2)如果你同時需要多個許可權,你可以用allOf屬性
@RequiresPermission(allOf = { Manifest.permission.READ_HISTORY_BOOKMARKS, Manifest.permission.WRITE_HISTORY_BOOKMARKS}) public static final void updateVisitedHistory(ContentResolver cr, String url, boolean real) ;
(3)對於intents的許可權,可以直接在定義的intent常量字串欄位上標註許可權需求(他們通常都已經被@SdkConstant註解標註過了)
@RequiresPermission(android.Manifest.permission.BLUETOOTH) public static final String ACTION_REQUEST_DISCOVERABLE = "android.bluetooth.adapter.action.REQUEST_DISCOVERABLE";
(4)對於content providers的許可權,你可能需要單獨的標註讀和寫的許可權訪問,所以可以用@Read或者@Write標註每一個許可權需求
@RequiresPermission.Read(@RequiresPermission(READ_HISTORY_BOOKMARKS)) @RequiresPermission.Write(@RequiresPermission(WRITE_HISTORY_BOOKMARKS)) public static final Uri BOOKMARKS_URI = Uri.parse("content://browser/bookmarks");
7.)Overriding Methods 註解: @CallSuper
如果你的API允許使用者重寫你的方法,但是呢,你又需要你自己的方法(父方法)在重寫的時候也被呼叫,這時候你可以使用@CallSuper標註
例如:Activity的onCreate函式
@CallSuper protected void onCreate(@Nullable Bundle savedInstanceState)
用了這個後,當重寫的方法沒有呼叫父方法時,工具就會給予標記提示
8.)Return Values註解: @CheckResult
如果你的方法返回一個值,你期望呼叫者用這個值做些事情,那麼你可以使用@CheckResult註解標註這個方法。
這個在具體使用中用的比較少,除非特殊情況,比如在專案中對一個資料進行處理,這個處理比較耗時,我們希望呼叫該函式的呼叫者在不需要處理結果的時候,提示沒有使用,酌情刪除呼叫。
9.)其他註解
Keep
:指出一個方法在被混淆的時候應該被保留。
VisibleForTesting
:可註解一個類,方法,或變數,表示有更寬鬆的可見性,這樣它能夠有更寬泛的可見性,使程式碼可以被測試。
10.)IntelliJ註解
IntelliJ,Android Studio就是基於它開發的,IntelliJ有一套它自己的註解;IntDef分析其實重用的是MagicConstant分析的程式碼,IntelliJ null分析其實用的是一組配置好的null註解。如果你執行Analyze > Infer Nullity…,它會試圖找出所有的null約束並新增他們。這個檢查有時會插入IntelliJ註解。你可以通過搜尋,替換為Android註解庫的註解,或者你也可以直接用IntelliJ註解。在build.gradle裡或者通過Project Structure對話方塊的Dependencies皮膚都可以新增如下依賴:
dependencies { compile 'com.intellij:annotations:12.0' }
小結:
經過查閱資料,系統了學習了Support Annotations註解,學以致用,通過這個Support Annotations可以提高程式碼可讀性,同時可以在類載入時就可以檢查一些錯誤,同時不會對效能有任何影響,因為Support Annotations中的註解的生命週期全部是RetentionPolicy.CLASS。接下來準備在專案中大量推廣使用。