Android注解支持(Support Annotations)

注解支持(Support Annotations)

Android support library從19.1版本開始引入了一個(gè)新的注解庫籽御,它包含很多有用的元注解绘盟,你能用它們修飾你的代碼,幫助你發(fā)現(xiàn)bug程奠。Support library自己本身也用到了這些注解,所以作為support library的用戶霹粥,Android Studio已經(jīng)基于這些注解校驗(yàn)了你的代碼并且標(biāo)注其中潛在的問題忆蚀。Support library 22.2版本又新增了13個(gè)新的注解以供使用欣鳖。

使用注解庫

注解默認(rèn)是沒有包含的;他們被包裝成一個(gè)獨(dú)立的庫矾缓。(support library現(xiàn)在由一些更小的庫組成:v4-support, appcompat, gridlayout, mediarouter等等)

(如果你正在使用appcompat庫样眠,那么你已經(jīng)可以使用這些注解了盟戏,因?yàn)閍ppcomat它自己也依賴它。)

添加使用注解最簡單的方式就是打開Project Structure對話框。首先在左邊選中module问窃,然后在右邊選中Dependencies標(biāo)簽頁亥鬓,點(diǎn)擊面板底部的+按鈕,選擇Library Dependency域庇,假設(shè)你已經(jīng)把Android Support Repository安裝到你的SDK中了嵌戈,那么注解庫將會(huì)出現(xiàn)在列表中,你只需點(diǎn)擊選中它即可(這里是列表中的第一個(gè))

添加依賴
點(diǎn)擊OK完成Project Structure的編輯听皿。這會(huì)修改你的build.gradle文件熟呛,當(dāng)然你也可以手動(dòng)編輯它:
dependencies { compile 'com.android.support:support-annotations:22.2.0'}

對于Android application和Android library這兩個(gè)類型的module(你應(yīng)用了com.android.application或者com.android.library插件的)來說,你需要做的已經(jīng)都做好了尉姨。如果你想只在Java module使用這些注解庵朝,那么你就明確的包含SDK倉庫了,因?yàn)閟upport libraries不能從jcenter獲得(Android Gradle插件會(huì)自動(dòng)的包含這些依賴啊送,但是Java插件卻沒有偿短。)

repositories {
   jcenter() 
   maven {
        url '<your-SDK-path>/extras/android/m2repository'
   }
}
執(zhí)行注解

當(dāng)你用Android Studio和IntelliJ的時(shí)候,如果給標(biāo)注了這些注解的方法傳遞錯(cuò)誤類型的參數(shù)馋没,那么IDE就會(huì)實(shí)時(shí)標(biāo)記出來昔逗。

從Gradle插件1.3.0-beta1版本開始,并且安裝了Android M Preview平臺(tái)工具的情況下篷朵,通過命令行調(diào)用gradle的lint
任務(wù)就可以執(zhí)行這些檢查勾怒。如果你想把標(biāo)記問題作為持續(xù)集成的一部分婆排,那么這種方式是非常有用的。說明:這并不包含nullness注解笔链。本文中所介紹的其他注解都可以通過lint執(zhí)行檢查段只。

Nullness Annotations

@Nullable注解能被用來標(biāo)注給定的參數(shù)或者返回值可以為null。
類似的鉴扫,@NonNull注解能被用來標(biāo)注給定的參數(shù)或者返回值不能為null赞枕。

如果一個(gè)本地變量的值為null(比如因?yàn)檫^早的代碼檢查它是否為null),而你又把它作為參數(shù)傳遞給了一個(gè)方法坪创,并且該方法的參數(shù)又被@NonNull標(biāo)注炕婶,那么IDE會(huì)提醒你,你有一個(gè)潛在的崩潰問題莱预。

   v4 support library中的FragmentActivity的示例代碼:

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

(如果你執(zhí)行Analyze > Infer Nullity柠掂,或者你在鍵入時(shí)把@NonNull替換成了@NotNull,那么IDE可能會(huì)提供附加的IntelliJ注解依沮。參考底部的“IntelliJ Annotations”段落了解更多)

注意@NonNull和@Nullable并不是對立的:還有第三種可能:未指定涯贞。當(dāng)你沒有指定@NonNull或者@Nullable的時(shí)候,工具就不能確定危喉,所以這個(gè)API也就不起作用宋渔。

最初,我們在findViewById方法上標(biāo)注@Nullable姥饰,從技術(shù)上說傻谁,這是正確的:findViewById可以返回null。但是如果你知道你在做什么的時(shí)候(如果你傳遞給他一個(gè)存在的id)他是不會(huì)返回null的列粪。當(dāng)我們使用@Nullable注解它的時(shí)候审磁,就意味著源代碼編輯器中會(huì)有大量的代碼出現(xiàn)高亮警告。如果你已經(jīng)意識(shí)到每次使用該方法都應(yīng)該明確的進(jìn)行null檢查岂座,那么就只能用@Nullable標(biāo)注返回值态蒂。有個(gè)經(jīng)驗(yàn)規(guī)則:看現(xiàn)有的“好的代碼”(比如審查產(chǎn)品代碼),看看這些API是怎么被使用的费什。如果該代碼為null檢查結(jié)果钾恢,你應(yīng)該為方法注解@Nullable。

資源類型注解

Android的資源值通常都是使用整型傳遞鸳址。這意味著獲取一個(gè)drawable使用的參數(shù)瘩蚪,也能很容易的傳遞給一個(gè)獲取string的方法;因?yàn)樗麄兌际莍nt類型稿黍,編譯器很難區(qū)分疹瘦。

資源類型注解可以在這種情況下提供類型檢查。比如一個(gè)被@StringRes住進(jìn)誒的int類型參數(shù)巡球,如果傳遞一個(gè)不是R.string類型的引用將會(huì)被IDE標(biāo)注:


資源類型注解以ActionBar為例:

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

有`很多不同資源類型的注解:如下的每一個(gè)Android資源類型:
@StringRes, @DrawableRes, @ColorRes, @InterpolatorRes,等等言沐。一般情況下邓嘹,如果有一個(gè)foo
類型的資源,那么它的相應(yīng)的資源類型注解就是FooRes.

除此之外险胰,還有一個(gè)名為@AnyRes特殊的資源類型注解汹押。它被用來標(biāo)注一個(gè)未知的特殊類型的資源,但是它必須是一個(gè)資源類型起便。比如在框架中棚贾,它被用在Resources#getResourceName(@AnyRes int resId)上,使用的時(shí)候缨睡,你可以這樣getResources().getResourceName(R.drawable.icon)用鸟悴,也可以getResources().getResourceName(R.string.app_name)這樣用陈辱,但是卻不能這樣getResources().getResourceName(42)用奖年。

請注意,如果你的API支持多個(gè)資源類型沛贪,你可以使用多個(gè)注解來標(biāo)注你的參數(shù)陋守。

IntDef/StringDef: 類型定義注解

整型除了可以作為資源的引用之外,也可以用作“枚舉”類型使用利赋。

@IntDef和”typedef”作用非常類似水评,你可以創(chuàng)建另外一個(gè)注解,然后用@IntDef指定一個(gè)你期望的整型常量值列表媚送,最后你就可以用這個(gè)定義好的注解修飾你的API了中燥。

appcompat庫里的一個(gè)例子:

import android.support.annotation.IntDef;
...
public abstract class ActionBar {
...
@IntDef({NAVIGATION_MODE_STANDARD, NAVIGATION_MODE_LIST, NAVIGATION_MODE_TABS})
@Retention(RetentionPolicy.SOURCE)
public @interface NavigationMode {}

public static final int NAVIGATION_MODE_STANDARD = 0;
public static final int NAVIGATION_MODE_LIST = 1;
public static final int NAVIGATION_MODE_TABS = 2;

@NavigationMode
public abstract int getNavigationMode();

public abstract void setNavigationMode(@NavigationMode int mode);

上面非注解的部分是現(xiàn)有的API。我們創(chuàng)建了一個(gè)新的注解(NavigationMode)并且用@IntDef標(biāo)注它,通過@IntDef我們?yōu)榉祷刂祷蛘邊?shù)指定了可用的常量值塘偎。我們還添加了@Retention(RetentionPolicy.SOURCE)告訴編譯器這個(gè)新定義的注解不需要被記錄在生成的.class文件中(譯者注:源代碼級別的疗涉,生成class文件的時(shí)候這個(gè)注解就被編譯器自動(dòng)去掉了)。

使用這個(gè)注解后吟秩,如果你傳遞的參數(shù)或者返回值不在指定的常量值中的話咱扣,IDE將會(huì)標(biāo)記出這種情況。

你也可以指定一個(gè)整型是一個(gè)標(biāo)記性質(zhì)的類型涵防;這樣客戶端代碼就通過|闹伪,&等操作符同時(shí)傳遞多個(gè)常量了:

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

最后,還有一個(gè)字符串版本的注解壮池,就是@StringDef偏瓤,它和@IntDef的作用基本上是一樣,所不同的是它是針對字符串的椰憋。該注解一般不常用厅克,但是有的時(shí)候非常有用,比如在限定向Activity#getSystemService方法傳遞的參數(shù)范圍的時(shí)候熏矿。

要了解關(guān)于類型注解的更多詳細(xì)信息已骇,請參考https://developer.android.com/tools/debugging/annotations.html#enum-annotations

(這些都是建立在IntelliJ’s MagicConstant注解的基礎(chǔ)上离钝,你可以在這里找到該注解的詳細(xì)信息:http://blog.jetbrains.com/idea/2012/02/new-magic-constant-inspection/)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市褪储,隨后出現(xiàn)的幾起案子卵渴,更是在濱河造成了極大的恐慌,老刑警劉巖鲤竹,帶你破解...
    沈念sama閱讀 217,277評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件浪读,死亡現(xiàn)場離奇詭異,居然都是意外死亡辛藻,警方通過查閱死者的電腦和手機(jī)碘橘,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評論 3 393
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來吱肌,“玉大人痘拆,你說我怎么就攤上這事〉” “怎么了纺蛆?”我有些...
    開封第一講書人閱讀 163,624評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長规揪。 經(jīng)常有香客問我桥氏,道長,這世上最難降的妖魔是什么猛铅? 我笑而不...
    開封第一講書人閱讀 58,356評論 1 293
  • 正文 為了忘掉前任字支,我火速辦了婚禮,結(jié)果婚禮上奸忽,老公的妹妹穿的比我還像新娘堕伪。我一直安慰自己,他們只是感情好月杉,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,402評論 6 392
  • 文/花漫 我一把揭開白布刃跛。 她就那樣靜靜地躺著,像睡著了一般苛萎。 火紅的嫁衣襯著肌膚如雪桨昙。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,292評論 1 301
  • 那天腌歉,我揣著相機(jī)與錄音蛙酪,去河邊找鬼。 笑死翘盖,一個(gè)胖子當(dāng)著我的面吹牛桂塞,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播馍驯,決...
    沈念sama閱讀 40,135評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼阁危,長吁一口氣:“原來是場噩夢啊……” “哼玛痊!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起狂打,我...
    開封第一講書人閱讀 38,992評論 0 275
  • 序言:老撾萬榮一對情侶失蹤擂煞,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后趴乡,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體对省,經(jīng)...
    沈念sama閱讀 45,429評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,636評論 3 334
  • 正文 我和宋清朗相戀三年晾捏,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了蒿涎。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,785評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡惦辛,死狀恐怖劳秋,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情裙品,我是刑警寧澤俗批,帶...
    沈念sama閱讀 35,492評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站市怎,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏辛慰。R本人自食惡果不足惜区匠,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,092評論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望帅腌。 院中可真熱鬧驰弄,春花似錦、人聲如沸速客。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽溺职。三九已至岔擂,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間浪耘,已是汗流浹背乱灵。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留七冲,地道東北人痛倚。 一個(gè)月前我還...
    沈念sama閱讀 47,891評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像澜躺,于是被迫代替她去往敵國和親蝉稳。 傳聞我的和親對象是個(gè)殘疾皇子抒蚜,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,713評論 2 354

推薦閱讀更多精彩內(nèi)容