日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Android >内容正文

Android

【Android APT】注解处理器 ( Element 注解节点相关操作 )

發布時間:2025/6/17 Android 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【Android APT】注解处理器 ( Element 注解节点相关操作 ) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

  • 一、獲取被 注解 標注的節點
  • 二、Element 注解節點類型
  • 三、VariableElement 注解節點相關操作
  • 四、注解處理器 完整代碼示例
  • 五、博客資源


Android APT 學習進階路徑 : 推薦按照順序閱讀 , 從零基礎到開發簡易 ButterKnife 注解框架的學習路徑 ;

  • 【Java 注解】注解簡介及作用
  • 【Java 注解】自定義注解 ( 注解屬性定義與賦值 )
  • 【Java 注解】自定義注解 ( 元注解 )
  • 【Java 注解】自定義注解 ( 注解解析 )
  • 【Java 注解】自定義注解 ( 使用注解實現簡單測試框架 )
  • 【Android APT】編譯時技術 ( ButterKnife 原理分析 )
  • 【Android APT】編譯時技術 ( 編譯時注解 和 注解處理器 依賴庫 )
  • 【Android APT】編譯時技術 ( 開發編譯時注解 )
  • 【Android APT】注解處理器 ( 注解標注 與 初始化方法 )
  • 【Android APT】注解處理器 ( 配置注解依賴、支持的注解類型、Java 版本支持 )
  • 【Android APT】注解處理器 ( Element 注解節點相關操作 )

上一篇博客 【Android APT】注解處理器 ( 配置注解依賴、支持的注解類型、Java 版本支持 ) 中 為 注解處理器 Module 添加了 編譯時注解 Module 依賴 , 并設置了支持該注解處理器 支持的 注解類型 , 和 支持的 Java 版本 ;

本篇博客開發 注解處理器 的 處理注解 , 生成代碼的核心邏輯 ;





一、獲取被 注解 標注的節點



處理注解的核心邏輯在 AbstractProcessor 中的 process 方法中實現 ;

@AutoService(Processor.class) public class Compiler extends AbstractProcessor {/*** 搜索 Android 代碼中的 BindView 注解* 并生成相關代碼* @param annotations* @param roundEnv* @return*/@Overridepublic boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {return false;} }

先獲取被注解標注的節點 , 搜索 BindView , 調用 process 方法的 RoundEnvironment roundEnv 參數的 getElementsAnnotatedWith 方法 , 即可搜索到整個 Module 中所有使用了 BindView 注解的元素 ;

// 搜索 BindView , 將 BindView 注解放在什么元素上 , 得到的就是相應類型的元素 // 根據 注解類型 獲取 被該注解類型 標注的元素 , 元素可能是類 , 方法 , 字段 ; // 通過 getElementsAnnotatedWith 方法可以搜索到整個 Module 中所有使用了 BindView 注解的元素 Set<? extends Element> elements = roundEnv.getElementsAnnotatedWith(BindView.class);

將 BindView 注解放在什么元素上 , 得到的就是相應類型的元素 , 根據 注解類型 獲取 被該注解類型 標注的元素 , 元素可能是類 , 方法 , 字段 ;


在 app 模塊中 , 只有 MainActivity 中的一個 屬性字段 使用 BindView 注解 , 調用 roundEnv.getElementsAnnotatedWith(BindView.class) 方法獲取的元素就是 MainActivity 中的 TextView hello 成員變量 ;

import android.os.Bundle; import android.widget.TextView; import androidx.appcompat.app.AppCompatActivity; import kim.hsl.annotation.BindView;public class MainActivity extends AppCompatActivity {@BindView(R.id.hello)TextView hello;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);} }

假設在 若干 Activity 中 , 若干位置 , 使用了 BindView 注解 , 那么在獲取的所有使用了 BindView 注解的字段 Set<? extends Element> elements 中裝載了所有的使用了該注解的字段 , 這些字段來自不同的 Activity 中 ;

這就需要將 Set<? extends Element> elements 中的 字段 按照 Activity 上下文進行分組 , 以便生成代碼 ;

這樣每個 Activity 界面都對應若干個 Set<? extends Element> elements 中的元素 ;





二、Element 注解節點類型



使用注解標注的 Element 節點類型 :

ExecutableElement : 使用注解的 方法 節點類型 ;

VariableElement : 使用注解的 字段 節點類型 , 類的成員變量 ;

TypeElement : 使用注解的 類 節點類型 ;

PackageElement : 使用注解的 包 節點類型 ;


上述 444 個類都是 javax.lang.model.element.Element 的子類 ;


@BindView 注解標注的都是 Activity 中的成員字段 , 當前獲取 Set<? extends Element> elements 集合中的節點都是 Field 字段對應的 VariableElement 類型的節點 ;





三、VariableElement 注解節點相關操作



遍歷上述 VariableElement 類型節點集合 , 將其中的元素按照 Activity 進行分組 , 將分組結果放到 HashMap<String, HashSet<VariableElement>> elementMap 鍵值對 Map 集合中 ;


要分組放置 注解節點 的 HashMap<String, HashSet<VariableElement>> elementMap 鍵值對 Map 集合 , 其中 " 鍵 " 是 注解標注的成員字段所在的 Activity 類的全類名 , " 值 " 是該 Activity 中所有使用 @BindView 注解的成員字段集合 ;

// @BindView 注解標注的都是 Activity 中的成員字段, // 上述 elements 中的元素都是 VariableElement 類型的節點 HashMap<String, HashSet<VariableElement>> elementMap = new HashMap<>();

給定 VariableElement 注解節點 , 獲取該節點的上一級節點 , 注解節點是 VariableElement , 成員字段節點 , 其上一級節點是就是 Activity 類對應的 類節點 TypeElement , 通過調用 VariableElement.getEnclosingElement 方法獲取上一級節點 , 類型是 TypeElement ;

// 將注解節點類型強轉為 VariableElement 類型 VariableElement ve = (VariableElement) element;// 獲取該注解節點對應的成員變量類名 // 先獲取該注解節點的上一級節點 , 注解節點是 VariableElement , 成員字段節點 // 上一級節點是就是 Activity 類節點對應的 類節點 TypeElement TypeElement te = (TypeElement) ve.getEnclosingElement();

獲取 TypeElement 注解節點 的全類名 , 調用 TypeElement.getQualifiedName 方法獲取 , 如果只獲取類名 , 不包含完整包名的話 , 調用 TypeElement.getSimpleName 方法獲取 ;

// 獲取 Activity 的全類名 String className = te.getQualifiedName().toString();

根據從 VariableElement 對象中獲取的上一級節點的類名 , 對 Set<? extends Element> elements 集合中的 VariableElement 類型元素進行分組 , 同一個 Activity 中對應的 注解節點 對象放在一個 HashSet<VariableElement> 集合中 , 然后放到 HashMap<String, HashSet<VariableElement>> elementMap 中 , 鍵是 Activity 全類名 ;

具體的集合操作參考下面的源碼示例 ;


部分代碼示例 :

/*** 搜索 Android 代碼中的 BindView 注解* 并生成相關代碼* @param annotations* @param roundEnv* @return*/@Overridepublic boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {// 搜索 BindView , 將 BindView 注解放在什么元素上 , 得到的就是相應類型的元素// 根據 注解類型 獲取 被該注解類型 標注的元素 , 元素可能是類 , 方法 , 字段 ;// 通過 getElementsAnnotatedWith 方法可以搜索到整個 Module 中所有使用了 BindView 注解的元素Set<? extends Element> elements = roundEnv.getElementsAnnotatedWith(BindView.class);// @BindView 注解標注的都是 Activity 中的成員字段,// 上述 elements 中的元素都是 VariableElement 類型的節點HashMap<String, HashSet<VariableElement>> elementMap = new HashMap<>();// 遍歷 elements 注解節點 , 為節點分組for (Element element : elements){// 將注解節點類型強轉為 VariableElement 類型VariableElement ve = (VariableElement) element;// 獲取該注解節點對應的成員變量類名// 先獲取該注解節點的上一級節點 , 注解節點是 VariableElement , 成員字段節點// 上一級節點是就是 Activity 類節點對應的 類節點 TypeElementTypeElement te = (TypeElement) ve.getEnclosingElement();// 獲取 Activity 的全類名String className = te.getQualifiedName().toString();mMessager.printMessage(Diagnostic.Kind.NOTE, "TypeElement : " + className + " , VariableElement : " + ve.getSimpleName());// 獲取 elementMap 集合中的 Activity 的全類名對應的 VariableElement 節點集合// 如果是第一次獲取 , 為空 ,// 如果之前已經獲取了該 Activity 的全類名對應的 VariableElement 節點集合, 那么不為空HashSet<VariableElement> variableElements = elementMap.get(className);if (variableElements == null){variableElements = new HashSet<>();// 創建之后 , 將集合插入到 elementMap 集合中elementMap.put(className, variableElements);}// 將本節點插入到 HashSet<VariableElement> variableElements 集合中variableElements.add(ve);}return false;}

編譯時 注解處理器 打印的內容 : 在 Build 面板 , " Build Output " 選項卡中輸入編譯相關信息 , 其中 " Task :app:compileDebugJavaWithJavac " 任務輸出 注解處理器 相關日志 ;





四、注解處理器 完整代碼示例



注解處理器 完整代碼示例 :

package kim.hsl.annotation_compiler;import com.google.auto.service.AutoService;import java.io.File; import java.util.HashMap; import java.util.HashSet; import java.util.Set; import javax.annotation.processing.AbstractProcessor; import javax.annotation.processing.Filer; import javax.annotation.processing.Messager; import javax.annotation.processing.ProcessingEnvironment; import javax.annotation.processing.Processor; import javax.annotation.processing.RoundEnvironment; import javax.annotation.processing.SupportedAnnotationTypes; import javax.annotation.processing.SupportedSourceVersion; import javax.lang.model.SourceVersion; import javax.lang.model.element.Element; import javax.lang.model.element.ExecutableElement; import javax.lang.model.element.PackageElement; import javax.lang.model.element.TypeElement; import javax.lang.model.element.VariableElement; import javax.tools.Diagnostic;import kim.hsl.annotation.BindView;/*** 生成代碼的注解處理器*/ @AutoService(Processor.class) public class Compiler extends AbstractProcessor {/*** 生成 Java 代碼對象*/private Filer mFiler;/*** 日志打印*/private Messager mMessager;/*** 初始化注解處理器相關工作* @param processingEnv*/@Overridepublic synchronized void init(ProcessingEnvironment processingEnv) {super.init(processingEnv);this.mFiler = processingEnv.getFiler();this.mMessager = processingEnv.getMessager();}/*** 聲明 注解處理器 要處理的注解類型* @return*/@Overridepublic Set<String> getSupportedAnnotationTypes() {Set<String> supportedAnnotationTypes = new HashSet<String>();// 將 BindView 全類名 kim.hsl.annotation.BinndView 放到 Set 集合中supportedAnnotationTypes.add(BindView.class.getCanonicalName());return supportedAnnotationTypes;}/*** 聲明支持的 JDK 版本* @return*/@Overridepublic SourceVersion getSupportedSourceVersion() {// 通過 ProcessingEnvironment 類獲取最新的 Java 版本并返回return processingEnv.getSourceVersion();}/*** 搜索 Android 代碼中的 BindView 注解* 并生成相關代碼* @param annotations* @param roundEnv* @return*/@Overridepublic boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {// 搜索 BindView , 將 BindView 注解放在什么元素上 , 得到的就是相應類型的元素// 根據 注解類型 獲取 被該注解類型 標注的元素 , 元素可能是類 , 方法 , 字段 ;// 通過 getElementsAnnotatedWith 方法可以搜索到整個 Module 中所有使用了 BindView 注解的元素Set<? extends Element> elements = roundEnv.getElementsAnnotatedWith(BindView.class);// @BindView 注解標注的都是 Activity 中的成員字段,// 上述 elements 中的元素都是 VariableElement 類型的節點HashMap<String, HashSet<VariableElement>> elementMap = new HashMap<>();// 遍歷 elements 注解節點 , 為節點分組for (Element element : elements){// 將注解節點類型強轉為 VariableElement 類型VariableElement ve = (VariableElement) element;// 獲取該注解節點對應的成員變量類名// 先獲取該注解節點的上一級節點 , 注解節點是 VariableElement , 成員字段節點// 上一級節點是就是 Activity 類節點對應的 類節點 TypeElementTypeElement te = (TypeElement) ve.getEnclosingElement();// 獲取 Activity 的全類名String className = te.getQualifiedName().toString();mMessager.printMessage(Diagnostic.Kind.NOTE, "TypeElement : " + className + " , VariableElement : " + ve.getSimpleName());// 獲取 elementMap 集合中的 Activity 的全類名對應的 VariableElement 節點集合// 如果是第一次獲取 , 為空 ,// 如果之前已經獲取了該 Activity 的全類名對應的 VariableElement 節點集合, 那么不為空HashSet<VariableElement> variableElements = elementMap.get(className);if (variableElements == null){variableElements = new HashSet<>();// 創建之后 , 將集合插入到 elementMap 集合中elementMap.put(className, variableElements);}// 將本節點插入到 HashSet<VariableElement> variableElements 集合中variableElements.add(ve);}return false;} }



五、博客資源



博客源碼 :

  • GitHub : https://github.com/han1202012/APT

  • CSDN :

總結

以上是生活随笔為你收集整理的【Android APT】注解处理器 ( Element 注解节点相关操作 )的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 天堂视频中文在线 | 97精品人妻一区二区三区香蕉 | 日日色综合 | jizz欧美大片 | 国产男女自拍 | 国产精品久久久久久久久久久久久久久久久久 | 深夜成人在线 | 玖玖在线播放 | 乳罩脱了喂男人吃奶视频 | 天天草天天射 | 天堂av8在线 | 欧美日韩三级在线观看 | 黄色视屏在线看 | 婷婷色图 | 国产精品一线二线三线 | 超碰97在线资源 | 麻豆视频入口 | 看全色黄大色黄大片女一次牛 | 日本免费中文字幕 | 久久久久亚洲av成人毛片韩 | 福利二区视频 | 五月综合色 | 91看片看淫黄大片 | 午夜伦理福利视频 | 人妻天天爽夜夜爽一区二区三区 | 欧州一区二区三区 | 日韩午夜三级 | 男人天堂a在线 | 亚洲性视频 | 在线免费色 | 亚洲成人网av | 一道本不卡视频 | 毛片9 | 黄色操人 | 免费毛片一区二区三区 | 怎么可能高潮了就结束漫画 | 亚洲精品自拍视频 | 国产精品第六页 | 五月天视频网 | 天天干夜夜嗨 | 美女扒开尿口来摸 | 免费在线观看成人av | 成人免费在线观看网站 | 国产成人久久精品流白浆 | 国产成a人亚洲精v品无码 | 国产成人毛毛毛片 | 欧美精品久久久久a | www.视频一区 | 松本一香在线播放 | 日日夜夜艹 | 一级做a爰片久久毛片 | 久久青青操 | 麻豆免费在线观看视频 | 乱淫av| 狠狠干网址| 在线免费观看不卡av | 高潮一区二区三区 | 国产春色 | 日本视频不卡 | 欧美激情啪啪 | 国产精品一区二区在线看 | 欧美一级无毛 | 村上凉子av| 国产成人久久精品麻豆二区 | 精品久久香蕉国产线看观看亚洲 | 成人免费午夜 | chien国产乱露脸对白 | 黄视频网站在线观看 | av一区二区三区在线观看 | 91免费版视频 | 国产电影一区在线观看 | 日本50路肥熟bbw | 国产乱妇无码大片在线观看 | 国产99久久久国产精品 | 精品视频免费在线观看 | 精品一二三四 | 国产稀缺真实呦乱在线 | 国产在线观看99 | 国产精品久久久午夜夜伦鲁鲁 | av片毛片 | 丁香婷婷网 | 日日爽夜夜| 精品国产av无码一区二区三区 | 精东传媒在线观看 | 99riav1国产精品视频 | 国产成人精品国内自产拍免费看 | jizjiz中国少妇高潮水多 | 青青草原国产在线观看 | 日韩大片在线 | 小毛片网站 | 无码人妻精品一区二区三区温州 | 日本精品区| 欧美激情一区二区三区 | 综合五月天 | 成人午夜久久 | 尤物网在线 | 呦呦av | 91九色国产在线 | 色鬼综合|