Android自定義注解

1艳吠、什么是注解

An annotation is a form of metadata, that can be added to Java source code. Classes, methods, variables, parameters and packages may be annotated. Annotations have no direct effect on the operation of the code they annotate.

翻譯:

注釋是元數據的一種形式陵吸,可以添加到Java源代碼中渔扎√寐龋可以注釋類误债、方法颗管、變量玫锋、參數和包。注釋對它們注釋的代碼的操作沒有直接影響权薯。

????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????--by 百度翻譯

個人理解注解就是一個標記姑躲,可以標記在類、字段盟蚣、方法等上面黍析,如果我們對這個標記不做任何處理那么其實它不起任何作用

2、元注解

元注解就是注解的注解屎开,主要有四個:@Target阐枣、@Retention、@Inherited奄抽、@Documented

比如:


其中Target表示注解的作用范圍取ElementType中的值

ElementType表示的作用范圍

Retention定義了注解在哪個級別可用蔼两,有三個取值:

RetentionPolicy.SOURCE:僅在源碼期間有效,在編譯期間被丟棄

RetentionPolicy.CLASS:保留到class文件中逞度,也就是說編譯期間都是可以對其進行處理的

RetentionPolicy.RUNTIME:保留到運行時额划,即可以用過反射調用


展示注解的級別

如上圖所示,定義了三個注解Test1档泽、Test2俊戳、Test3其中Test3是SOURCE級別的所以我們在反編譯出來的dex文件中看不到Test3揖赴,Test1和Test2則可以看到。如果我們繼續(xù)編寫代碼在運行期間反射的話那么Test2是可以被反射到的抑胎,Test1則找不到燥滑。(代碼不好貼,可以自行驗證)


Inherited表示注解是否可以被繼承圆恤,意思是如果A被注解@Test1注解突倍,B繼承A,如果@Test1被Inherited標記那么classB.getAnnotation可以獲取到Test1盆昙,如果@Test1沒有被Inherited標記那么那么classB.getAnnotation就無法獲取到Test1羽历。(代碼不好貼,可以自行驗證)


如上圖代碼所示淡喜,Handler3繼承Handler2秕磷,Handler2被Test2注解,Test2被Inherited注解炼团,然后運行程序打印log:

annotation: @annotation.test.jyb.com.annotation.Test2(value=101)澎嚣,可以發(fā)現(xiàn)通過Handler3我們可以取到Test2注解


Documented表示注解是否會保留到文檔中


3、AbstractProcessor

AbstractProcessor只能在java library工程里面用瘟芝,在Android library里面找不到這個類易桃,定義編譯期間注解最核心的是要用到AbstractProcessor用于處理我們的注解,它有四個方法可以讓我們重寫

?1锌俱、 public synchronized void init(ProcessingEnvironment processingEnv)

? 2晤郑、 public Set getSupportedAnnotationTypes()

? 3、 public SourceVersion getSupportedSourceVersion()

? 4贸宏、 public boolean process(Set annotations, RoundEnvironment roundEnv)

init方法主要是用于初始化和獲取相關工具類造寝,Init:初始化工作,獲取工具類:

processingEnv.getElementUtils(): element操作相關工具類吭练;

processingEnv.getTypeUtils():type操作相關工具類诫龙;

processingEnv.getMessager():打印日志;

processingEnv.getFiler()鲫咽,生成java文件签赃;

processingEnv.getOptions(), 獲取gradle中配置的參數

其中用的比較多的是打印日志和生成java文件

getSupportedAnnotationTypes:配置processor處理的注解類分尸。就是指定當前process處理哪幾個注解(我們可能會定義多個注解姊舵,用多個process進行處理,這個函數告訴當前process處理哪幾個注解)

getSupportedSourceVersion: 設置支持的java版本寓落,一般設置為SourceVersion.latestSupported()

process處理注解的方法,主要是獲取注解然后根據注解生成代碼


4荞下、定義編譯期注解

下面用一個例子來說民如何定義編譯期間注解伶选,

第一步定義注解:


定義注解

如上圖史飞,我們定義了一個注解可以用在類、方法仰税、字段上面构资,CLASS級別(無法反編譯獲取)陨簇,可以被繼承

第二步編寫process方法

新建java library工程吐绵,編寫我們的process類繼承AbstractProcessor

編寫process類

這里我們的注解上也添加了一個@AutoService注解,這個AutoService作用是我們不用新建resources文件夾和配置文件河绽。使用方法就是在當前java library工程中添加Gradle依賴(implementation'com.google.auto.service:auto-service:1.0-rc4')然后在process類上添加注解就行


設置Procerssor能夠處理的注解

設置能夠處理的注解

重寫process方法

重寫process

上面process方法己单,首先通過roundEnv獲取被Test1標記的類或者方法或者字段,如果沒有找到那么退出

TypeSpec.Builder用于生成一個類(使用javapoet庫幫助我們生成代碼)

第三部添加一個單例方法(也是使用javapoet庫)

for循環(huán)耙饰,element就是被注解標記的元素纹笼,先判斷它是否是類如果是那么添加成員函數

最后createFile生成代碼。

addInstanceMethod
addClassMember
createFile

addInstanceMethod苟跪,addClassMember都是通過javapoet來生成方法和字段的廷痘,createFile生成java文件。最后編譯我們可以在

app\build\intermediates\classes\debug\annotation\test\jyb\com中查看件已,標黑的這個是我們生成類的時候設置的包名笋额,所以它會隨著包名的變化而變化


這個是自動生成的代碼

4、定義運行期間注解

定義運行期間注解比較簡單篷扩,就是在定義注解的時候將Retention設置為RunTime然后通過反射調用就行兄猩,比如我們如果要用運行期間注解實現(xiàn)ButterKnife的話需要以下步驟:

第一步定義注解:

定義注解

第二部編寫輔助代碼

通過反射注解調用findViewById方法

第三步使用

使用注解

然后在Activity的Oncreate方法中調用InjectBindHelper.inject(this)即可,因為反射效率比較低所以一般不會用這種方法來用findViewById瞻惋,這里只是演示;


完整demo:https://github.com/yaozhukuang/component,這個demo是通過注解實現(xiàn)項目組件化方案厦滤,所以代碼跟文中的可能有不一樣

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市歼狼,隨后出現(xiàn)的幾起案子掏导,更是在濱河造成了極大的恐慌,老刑警劉巖羽峰,帶你破解...
    沈念sama閱讀 217,826評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件趟咆,死亡現(xiàn)場離奇詭異,居然都是意外死亡梅屉,警方通過查閱死者的電腦和手機值纱,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,968評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來坯汤,“玉大人虐唠,你說我怎么就攤上這事《枘簦” “怎么了疆偿?”我有些...
    開封第一講書人閱讀 164,234評論 0 354
  • 文/不壞的土叔 我叫張陵咱筛,是天一觀的道長。 經常有香客問我杆故,道長迅箩,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,562評論 1 293
  • 正文 為了忘掉前任处铛,我火速辦了婚禮饲趋,結果婚禮上,老公的妹妹穿的比我還像新娘撤蟆。我一直安慰自己奕塑,他們只是感情好,可當我...
    茶點故事閱讀 67,611評論 6 392
  • 文/花漫 我一把揭開白布枫疆。 她就那樣靜靜地躺著爵川,像睡著了一般。 火紅的嫁衣襯著肌膚如雪息楔。 梳的紋絲不亂的頭發(fā)上寝贡,一...
    開封第一講書人閱讀 51,482評論 1 302
  • 那天,我揣著相機與錄音值依,去河邊找鬼圃泡。 笑死,一個胖子當著我的面吹牛愿险,可吹牛的內容都是我干的颇蜡。 我是一名探鬼主播,決...
    沈念sama閱讀 40,271評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼辆亏,長吁一口氣:“原來是場噩夢啊……” “哼风秤!你這毒婦竟也來了?” 一聲冷哼從身側響起扮叨,我...
    開封第一講書人閱讀 39,166評論 0 276
  • 序言:老撾萬榮一對情侶失蹤缤弦,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后彻磁,有當地人在樹林里發(fā)現(xiàn)了一具尸體碍沐,經...
    沈念sama閱讀 45,608評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,814評論 3 336
  • 正文 我和宋清朗相戀三年衷蜓,在試婚紗的時候發(fā)現(xiàn)自己被綠了累提。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,926評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡磁浇,死狀恐怖斋陪,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤鳍贾,帶...
    沈念sama閱讀 35,644評論 5 346
  • 正文 年R本政府宣布鞍匾,位于F島的核電站,受9級特大地震影響骑科,放射性物質發(fā)生泄漏。R本人自食惡果不足惜构拳,卻給世界環(huán)境...
    茶點故事閱讀 41,249評論 3 329
  • 文/蒙蒙 一咆爽、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧置森,春花似錦斗埂、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,866評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至行贪,卻和暖如春漾稀,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背建瘫。 一陣腳步聲響...
    開封第一講書人閱讀 32,991評論 1 269
  • 我被黑心中介騙來泰國打工崭捍, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人啰脚。 一個月前我還...
    沈念sama閱讀 48,063評論 3 370
  • 正文 我出身青樓殷蛇,卻偏偏與公主長得像,于是被迫代替她去往敵國和親橄浓。 傳聞我的和親對象是個殘疾皇子粒梦,可洞房花燭夜當晚...
    茶點故事閱讀 44,871評論 2 354

推薦閱讀更多精彩內容