日韩性视频-久久久蜜桃-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 注解节点相关操作 )的全部內容,希望文章能夠幫你解決所遇到的問題。

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

主站蜘蛛池模板: 成人精品一区二区三区视频 | 日日操夜夜操视频 | 日本一二三区在线 | 久久性生活 | 色黄网站在线观看 | 美女被娇喘流出白 | 一级黄色网 | 国产高清一区二区 | 中文字幕5566 | 亚洲综合网在线观看 | www.jizz国产 | 国产黄a三级三级看三级 | 就爱av| 日韩成人免费电影 | 成人自拍一区 | 欧美激情日韩 | 欧美日韩另类在线 | 庆余年三 | 操模特| 99re这里只有精品在线 | 欧美熟妇精品久久久久久 | 强行无套内谢大学生初次 | 美女一级片 | 影音先锋啪啪资源 | 亚洲成人av一区二区三区 | 免费观看黄一级视频 | 国产精彩视频一区二区 | 久操视频免费 | 国产美女毛片 | 亚洲av无码不卡一区二区三区 | 久久精品久久久 | 欧美中文字幕在线 | 韩国久久久久久 | 在线观看免费毛片 | 韩日视频在线观看 | 一级黄色美女 | 啪视频在线 | av大帝在线| av永久免费 | 悟空影视大全免费高清观看在线 | 久久最新精品 | 亚洲欧美电影 | 香蕉视频官方网站 | 四虎影视免费永久观看在线 | bl无遮挡高h动漫 | 亚洲一级色 | 国产古装艳史毛片hd | 日韩av无码一区二区三区 | 另类小说av| 日韩视频网 | 麻豆精品视频在线观看 | 国产女同91疯狂高潮互磨 | 日韩亚洲欧美中文字幕 | 国产精九九网站漫画 | 精品人妻一区二区三区免费 | 日本一二三区在线视频 | 国产综合网站 | 国产黑丝精品 | 欧美久草视频 | 污视频网站免费 | 欧洲精品在线观看 | 高清成人免费视频 | 免费视频二区 | 6080午夜伦理| www污网站 | 爱情岛亚洲论坛入口 | 乌克兰少妇性做爰 | 色姐 | 久久亚洲av成人无码国产电影 | 极品videosvideo喷水 | 99免费视频 | 国产精品久久午夜夜伦鲁鲁 | 一级黄色在线视频 | 色大师在线观看 | 又色又爽又高潮免费视频国产 | av一起看香蕉 | 日批免费观看 | 欧美在线看片 | 亚洲一区二区国产精品 | 国产精品伦一区二区三区免费看 | 91文字幕巨乱亚洲香蕉 | 五月天综合社区 | 色www情| 91片黄在线观 | 婷婷综合视频 | 久久久久亚洲AV成人网人人小说 | 精品亚洲中文字幕 | 久久精品美乳 | 成人女同在线观看 | 男人插女人下面视频 | 久久久精品在线观看 | 高清一二三区 | a点w片| 57pao成人国产永久免费视频 | 91免费国产视频 | avwww.| 精品视频在线观看一区 | 天天干少妇 | 成人短视频在线播放 |