Android Annotation Processor

Android開發(fā)中,注解平時我們用的比較多,也許我們會比較好奇辐董,注解的背后是如何工作的,這篇文章幫大家一步步創(chuàng)建一個簡單的注解處理器禀综。

一简烘、創(chuàng)建工程

環(huán)境:AndroidStudio 3.4.2

1、創(chuàng)建項目

打開AndroidStudio定枷,創(chuàng)建一個新的項目AnnotationDemo孤澎,語言選Java,不要勾選androidx支持欠窒。

2覆旭、創(chuàng)建一個新的Java Libray

創(chuàng)建Modue.png

選擇JavaLibray.png

library名稱填processor


image.png

二、創(chuàng)建注解處理器

1岖妄、創(chuàng)建注解類
在processor module下新建一個注解類Greet

@Retention(RetentionPolicy.CLASS)
@Target(ElementType.TYPE)
public @interface Greet {
    String[] value() default "";
}
image.png

2型将、對上一步的注解創(chuàng)建注解處理器

在processor module下新建一個注解處理器類GreetProcessor

// 這里填寫要處理的注解類
@SupportedAnnotationTypes("xh.destiny.processor.Greet")
@SupportedSourceVersion(SourceVersion.RELEASE_8)
public class GreetProcessor extends AbstractProcessor {
    @Override
    public boolean process(Set<? extends TypeElement> set, RoundEnvironment roundEnv) {
        // 1.獲取類型信息
        Collection<? extends Element> annotatedElements = roundEnv.getElementsAnnotatedWith(Greet.class);
        List<TypeElement> types = ElementFilter.typesIn(annotatedElements);
        String packageName = null;
        String[] names = null;

        for (TypeElement type : types) {
            PackageElement packageElement = (PackageElement) type.getEnclosingElement();
            packageName = packageElement.getQualifiedName().toString();
            names = type.getAnnotation(Greet.class).value();
        }

        if (packageName == null) return false;

        // 2.構造Java代碼
        StringBuilder builder = new StringBuilder()
                .append("package " + packageName + ";\n\n")
                .append("public class Greeter {\n\n")
                .append("   public static String hello() {\n")
                .append("       return \"Hello ");

        for (int i = 0; i < names.length; i++) {
            if (i == 0) {
                builder.append(names[i]);
            } else {
                builder.append(", ").append(names[i]);
            }
        }

        builder.append("!\";\n")
                .append("   }\n")
                .append("}\n");

        // 3.生成Java源文件
        try {
            JavaFileObject javaFileObject = processingEnv.getFiler().createSourceFile(packageName + ".Greeter");
            Writer writer = javaFileObject.openWriter();
            writer.write(builder.toString());
            writer.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return false;
    }
}
image.png

到這里我們創(chuàng)建了一個注解和一個注解處理器,但是Java虛擬機并不知道如何使用這個注解處理器荐虐,因此我們還需要注冊下這個處理器七兜。

3、注冊注解處理器

在processor/src/main目錄下新建resources文件夾福扬,然后再在resources目錄下新建resources/META-INF和resources/META-INF/services兩個文件夾腕铸,注意,是兩個文件夾忧换。

然后再在resources/META-INF/services目錄下新建javax.annotation.processing.Processor文件恬惯,這個文件名稱請不要拼錯!在這個文件中填寫我們寫好的注解處理器GreetProcessor亚茬,完成后的文件如下:

image.png

三酪耳、關聯(lián)processor module到app module

打開app的build.gradle,在dependencies中添加如下代碼:

dependencies {
    ...

    implementation project(':processor')
    annotationProcessor project(':processor')
}
image.png

四、設置編譯版本

最后需要設置下編譯環(huán)境.

1.在processor module的build.gradle中添加如下代碼

sourceCompatibility = "8"
targetCompatibility = "8"
image.png

2.在app module的build.gradle中添加如下代碼

 compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
  }
image.png

四碗暗、測試成果

到這里我們的注解處理器就算完成了颈将,讓我們測試下。

在MainActivity上添加Greet注解


image.png

執(zhí)行Build -> rebuild project言疗,我們可以看到build目錄下已經(jīng)生成Greeter類了晴圾,大功告成。


image.png

其他

上述項目Greeter類的生成代碼是手寫的噪奄,有很多更加高效的方案可以替代死姚,如Apache Velocity模版、JavaPoet勤篮。這兩種方案在下面項目中有寫都毒,分別在velocity分支和javapoet分支,master分支是手寫的方式碰缔,所以注意切換分支查看账劲。

項目Demo地址

參考文章

美女教寫自定義注解處理器part1

美女教寫自定義注解處理器part2

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市金抡,隨后出現(xiàn)的幾起案子瀑焦,更是在濱河造成了極大的恐慌,老刑警劉巖梗肝,帶你破解...
    沈念sama閱讀 222,183評論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件榛瓮,死亡現(xiàn)場離奇詭異,居然都是意外死亡统捶,警方通過查閱死者的電腦和手機榆芦,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,850評論 3 399
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來喘鸟,“玉大人,你說我怎么就攤上這事驻右∈埠冢” “怎么了?”我有些...
    開封第一講書人閱讀 168,766評論 0 361
  • 文/不壞的土叔 我叫張陵堪夭,是天一觀的道長愕把。 經(jīng)常有香客問我,道長森爽,這世上最難降的妖魔是什么恨豁? 我笑而不...
    開封第一講書人閱讀 59,854評論 1 299
  • 正文 為了忘掉前任,我火速辦了婚禮爬迟,結(jié)果婚禮上橘蜜,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好计福,可當我...
    茶點故事閱讀 68,871評論 6 398
  • 文/花漫 我一把揭開白布跌捆。 她就那樣靜靜地躺著,像睡著了一般象颖。 火紅的嫁衣襯著肌膚如雪佩厚。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,457評論 1 311
  • 那天说订,我揣著相機與錄音抄瓦,去河邊找鬼。 笑死陶冷,一個胖子當著我的面吹牛钙姊,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播埃叭,決...
    沈念sama閱讀 40,999評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼摸恍,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了赤屋?” 一聲冷哼從身側(cè)響起立镶,我...
    開封第一講書人閱讀 39,914評論 0 277
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎类早,沒想到半個月后媚媒,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,465評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡涩僻,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,543評論 3 342
  • 正文 我和宋清朗相戀三年缭召,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片逆日。...
    茶點故事閱讀 40,675評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡嵌巷,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出室抽,到底是詐尸還是另有隱情搪哪,我是刑警寧澤,帶...
    沈念sama閱讀 36,354評論 5 351
  • 正文 年R本政府宣布坪圾,位于F島的核電站晓折,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏兽泄。R本人自食惡果不足惜漓概,卻給世界環(huán)境...
    茶點故事閱讀 42,029評論 3 335
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望病梢。 院中可真熱鬧胃珍,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,514評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至缔莲,卻和暖如春哥纫,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背痴奏。 一陣腳步聲響...
    開封第一講書人閱讀 33,616評論 1 274
  • 我被黑心中介騙來泰國打工蛀骇, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人读拆。 一個月前我還...
    沈念sama閱讀 49,091評論 3 378
  • 正文 我出身青樓擅憔,卻偏偏與公主長得像,于是被迫代替她去往敵國和親檐晕。 傳聞我的和親對象是個殘疾皇子暑诸,可洞房花燭夜當晚...
    茶點故事閱讀 45,685評論 2 360

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