亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

APT技術

2019-11-09 17:49:54
字體:
來源:轉載
供稿:網友

官方文檔:Getting Started with the Annotation PRocessing Tool (apt)

Annotation

如果想學習APT,那么就必須先了解Annotation的基礎,這里附加我另外一篇文章的地址: Annotation - QQ_20198405的博客 - 博客頻道 - CSDN.NET

APT

APT(Annotation Processing Tool)是一種處理注解的工具,它對源代碼文件進行檢測找出其中的Annotation,使用Annotation進行額外的處理。 Annotation處理器在處理Annotation時可以根據源文件中的Annotation生成額外的源文件和其它的文件(文件具體內容由Annotation處理器的編寫者決定),APT還會編譯生成的源文件和原來的源文件,將它們一起生成class文件。

創建Annotation Module

新建一個名稱為annotation的java Library,主要放置一些項目中需要使用到的Annotation和關聯代碼。 這里簡單自定義了一個注解:

@Target(ElementType.TYPE)@Retention(RetentionPolicy.CLASS)public @interface AptAnnotation {}

配置build.gradle

apply plugin: 'java'dependencies { compile fileTree(dir: 'libs', include: ['*.jar'])}sourceCompatibility = "1.7"targetCompatibility = "1.7"

創建Compiler Module

新建一個名為compiler的Java Library,這個類將會寫代碼生成的相關代碼。核心就是在這里。

配置build.gradle

apply plugin: 'java'tasks.withType(JavaCompile) { options.encoding = "UTF-8"}dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) compile 'com.google.auto.service:auto-service:1.0-rc2' compile 'com.squareup:javapoet:1.7.0' compile project(':annotation')}sourceCompatibility = "1.7"targetCompatibility = "1.7"AutoService 主要的作用是注解 processor 類,并對其生成 META-INF 的配置信息。JavaPoet 這個庫的主要作用就是幫助我們通過類調用的形式來生成代碼。tasks.withType是設置編碼格式,避免AptProcesser 中的中文注釋報錯依賴上面創建的annotation Module。

定義Processor類

生成代碼相關的邏輯就放在這里。

@AutoService(Processor.class) public class AptProcesser extends AbstractProcessor { @Override public Set<String> getSupportedAnnotationTypes() { return Collections.singleton(AptAnnotation.class.getCanonicalName()); } @Override public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { return false; } }

生成第一個類

我們接下來要生成下面這個HelloWorld的代碼:

package com.example.helloworld; public final class HelloWorld { public static void main(String[] args) { System.out.println("Hello, JavaPoet!"); } }

修改上述AptProcesser 的process方法

@Override public boolean process(Set<? extends TypeElement> set, RoundEnvironment roundEnvironment) { MethodSpec main = MethodSpec.methodBuilder("main") .addModifiers(Modifier.PUBLIC, Modifier.STATIC) .returns(void.class) .addParameter(String[].class, "args") .addStatement("$T.out.println($S)", System.class, "Hello, JavaPoet!") .build(); TypeSpec helloWorld = TypeSpec.classBuilder("HelloWorld") .addModifiers(Modifier.PUBLIC, Modifier.FINAL) .addMethod(main) .build(); JavaFile javaFile = JavaFile.builder("com.example.helloworld", helloWorld) .build(); try { javaFile.writeTo(processingEnv.getFiler()); } catch (IOException e) { e.printStackTrace(); } return false; }

在app中使用

配置項目根目錄的build.gradle

dependencies { classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'}

配置app的build.gradle

apply plugin: 'com.android.application'apply plugin: 'com.neenbedankt.android-apt'//...dependencies { //.. compile project(':annotation') apt project(':compiler')}

編譯使用

@AptAnnotationpublic class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); }}

點擊Android Studio的ReBuild Project,可以在在app的 build/generated/source/apt/debug 目錄下,即可看到生成的代碼。

基于注解的View注入:DIActivity

到目前我們還沒有使用注解,上面的@AptAnnotation 也沒有實際用上,下面我們做一些更加實際的代碼生成。實現基于注解的View,代替項目中的findByView 。這里僅僅是學習怎么用APT,如果真的想用DI框架,推薦使用ButterKnife,功能全面。

第一步,在annotation module創建@DIActivity、@DIView注解。

@Target(ElementType.TYPE)@Retention(RetentionPolicy.CLASS)public @interface DIActivity {}@Target(ElementType.FIELD)@Retention(RetentionPolicy.RUNTIME)public @interface DIView { int value() default 0;}

第二步,創建Diprocessor方法

@AutoService(Processor.class)public class DIProcessor extends AbstractProcessor { private Elements elementUtils; @Override public Set<String> getSupportedAnnotationTypes() { // 規定需要處理的注解 return Collections.singleton(DIActivity.class.getCanonicalName()); } @Override public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { System.out.println("DIProcessor"); Set<? extends Element> elements = roundEnv.getElementsAnnotatedWith(DIActivity.class); for (Element element : elements) { // 判斷是否Class TypeElement typeElement = (TypeElement) element; List<? extends Element> members = elementUtils.getAllMembers(typeElement); MethodSpec.Builder bindViewMethodSpecBuilder = MethodSpec.methodBuilder("bindView") .addModifiers(Modifier.PUBLIC, Modifier.STATIC) .returns(TypeName.VOID) .addParameter(ClassName.get(typeElement.asType()), "activity"); for (Element item : members) { DIView diView = item.getAnnotation(DIView.class); if (diView == null){ continue; } bindViewMethodSpecBuilder.addStatement(String.format("activity.%s = (%s) activity.findViewById(%s)",item.getSimpleName(),ClassName.get(item.asType()).toString(),diView.value())); } TypeSpec typeSpec = TypeSpec.classBuilder("DI" + element.getSimpleName()) .addModifiers(Modifier.PUBLIC, Modifier.FINAL) .addMethod(bindViewMethodSpecBuilder.build()) .build(); JavaFile javaFile = JavaFile.builder(getPackageName(typeElement), typeSpec).build(); try { javaFile.writeTo(processingEnv.getFiler()); } catch (IOException e) { e.printStackTrace(); } } return true; } private String getPackageName(TypeElement type) { return elementUtils.getPackageOf(type).getQualifiedName().toString(); } @Override public synchronized void init(ProcessingEnvironment processingEnv) { super.init(processingEnv); elementUtils = processingEnv.getElementUtils(); } @Override public SourceVersion getSupportedSourceVersion() { return SourceVersion.RELEASE_7; }}

第三步,使用DIActivity

@AptAnnotation@DIActivitypublic class MainActivity extends AppCompatActivity { @DIView(R.id.text1) TextView textView1; @DIView(R.id.text2) TextView textView2; @DIView(R.id.text3) TextView textView3; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); DIMainActivity.bindView(this); textView1.setText("text1"); textView2.setText("text2"); textView3.setText("text3"); }}

實際上就是通過apt生成以下代碼:

public final class DIMainActivity { public static void bindView(MainActivity activity) { activity.textView1 = (android.widget.TextView) activity.findViewById(2131427413); activity.textView2 = (android.widget.TextView) activity.findViewById(2131427414); activity.textView3 = (android.widget.TextView) activity.findViewById(2131427415); }}

常用方法

常用Element子類

TypeElement:類ExecutableElement:成員方法

VariableElement:成員變量

通過包名和類名獲取TypeName

TypeName targetClassName = ClassName.get("PackageName", "ClassName");通過Element獲取TypeNameTypeName type = TypeName.get(element.asType());獲取TypeElement的包名String packageName = processingEnv.getElementUtils().getPackageOf(type).getQualifiedName().toString();獲取TypeElement的所有成員變量和成員方法List<? extends Element> members = processingEnv.getElementUtils().getAllMembers(typeElement);

總結:

推薦閱讀dagger2、dbflow、ButterKnife等基于apt的開源項目代碼。JavaPoet 也有很多例子可以學習。

源碼傳送 參考: Android APT(編譯時代碼生成)最佳實踐 - 推酷 例子: 代碼傳送(稍加注釋) Android 利用 APT 技術在編譯期生成代碼 - hb707934728的博客 - 博客頻道 - CSDN.NET

相關文章: android-apt 翻譯 - 簡書 原文hvisser / android-apt — Bitbucket Annotation-Processing-Tool詳解 | qiushao http://qiushao.net/2015/07/07/Annotation-Processing-Tool%E8%AF%A6%E8%A7%A3/ AndroidSutdio 編譯時自動生成源代碼 | Septenary http://www.septenary.cn/2015/12/19/AndroidSutdio-%E7%BC%96%E8%AF%91%E6%97%B6%E8%87%AA%E5%8A%A8%E7%94%9F%E6%88%90%E6%BA%90%E4%BB%A3%E7%A0%81/


Android 打造編譯時注解解析框架 這只是一個開始 - Hongyang - 博客頻道 - CSDN.NET http://blog.csdn.net/lmj623565791/article/details/43452969 Android 如何編寫基于編譯時注解的項目 - Hongyang - 博客頻道 - CSDN.NET http://blog.csdn.net/lmj623565791/article/details/51931859

bug解決: Android Studio出現Error:No service of type Factor… - 簡書 http://www.jianshu.com/p/c4f4894ad215 Android Studio Error—Gradle: 錯誤:編碼 GBK 的不可映射字符的 - 黑暗領域 - 博客頻道 - CSDN.NET http://blog.csdn.net/sljjyy/article/details/11976099


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
亚洲欧美日韩中文视频| 色天天综合狠狠色| 亚洲欧美日韩精品久久奇米色影视| 欧美激情影音先锋| 亚洲男人的天堂在线| 91麻豆国产语对白在线观看| 国产欧美精品一区二区三区-老狼| 日韩av在线播放资源| 日韩中文字幕欧美| 欧洲美女7788成人免费视频| 九九热精品视频国产| 欧美激情在线狂野欧美精品| 日韩欧美亚洲范冰冰与中字| 欧美精品videos另类日本| 亚洲影视九九影院在线观看| 欧美日韩国产精品一区二区不卡中文| 久久成人亚洲精品| 亚洲成人国产精品| 国产视频一区在线| 欧美激情图片区| 欧美激情久久久久| 日本国产高清不卡| 全色精品综合影院| 成人欧美一区二区三区黑人孕妇| 日本国产欧美一区二区三区| 在线不卡国产精品| 日韩电影在线观看中文字幕| 久久99久久99精品免观看粉嫩| 欧美电影免费观看| 欧美大片免费观看在线观看网站推荐| 亚洲精品久久久久久久久久久久| 影音先锋日韩有码| 中文字幕免费精品一区| 国产精品久久二区| 亚洲成人av资源网| 国产99视频在线观看| 欧美大肥婆大肥bbbbb| 欧美视频在线观看 亚洲欧| 91精品久久久久久久久久久久久久| 亚洲美女动态图120秒| 精品高清一区二区三区| 欧美精品电影免费在线观看| 北条麻妃一区二区在线观看| 欧美激情xxxx性bbbb| 欧美在线观看网址综合| 最近更新的2019中文字幕| 97av视频在线| 国产精品国产三级国产aⅴ浪潮| 国产一区二区欧美日韩| 国产精品香蕉在线观看| 欧美激情第一页xxx| 国产视频精品免费播放| 久久伊人精品天天| 国产91网红主播在线观看| 午夜伦理精品一区| 91久久国产精品91久久性色| 怡红院精品视频| 另类天堂视频在线观看| 亚洲三级 欧美三级| 欧美黄网免费在线观看| 国产精品美乳一区二区免费| 国产亚洲精品久久久久动| 国产日韩欧美综合| 4k岛国日韩精品**专区| 97视频在线观看视频免费视频| 国产精品极品在线| 亚洲欧洲免费视频| 亚洲精品一区二区网址| 国产+成+人+亚洲欧洲| 亚洲缚视频在线观看| 91精品久久久久久久久久另类| 国产精品久久999| 国产精品jizz在线观看麻豆| 欧美裸体视频网站| 韩国精品美女www爽爽爽视频| 久久视频国产精品免费视频在线| 2019日本中文字幕| 欧美极品少妇xxxxⅹ裸体艺术| 欧美精品午夜视频| 国产+人+亚洲| 国产精品久久久久高潮| 亚洲剧情一区二区| 伊人精品在线观看| 欧美一性一乱一交一视频| 91中文字幕在线观看| 国产91网红主播在线观看| 欧美在线视频免费| 97视频国产在线| 日本高清久久天堂| 91av在线不卡| 亚洲欧美精品一区二区| 九九精品在线播放| 亚洲免费电影在线观看| 国产欧美在线观看| 日韩欧美亚洲综合| 国产精品一区二区三区免费视频| 日韩av最新在线观看| 波霸ol色综合久久| 少妇高潮久久久久久潘金莲| 疯狂做受xxxx高潮欧美日本| 久久精品成人一区二区三区| 久久手机免费视频| 欧美精品中文字幕一区| 国产精品69久久久久| 欧美日韩福利视频| 久久精品这里热有精品| 性欧美长视频免费观看不卡| 日韩精品黄色网| 久久精品国产成人精品| 亚洲欧美中文日韩在线| 成人性生交大片免费观看嘿嘿视频| 国产丝袜一区二区| 久久91精品国产91久久久| 久久成年人免费电影| 日韩av最新在线观看| 国产精品自拍偷拍| 日韩在线一区二区三区免费视频| 国产日韩欧美日韩大片| 欧美一级大片在线免费观看| 欧美一级bbbbb性bbbb喷潮片| 亚洲成人教育av| 亚洲bt天天射| 亚洲国产成人精品久久| 亚洲成色777777在线观看影院| 日韩中文在线中文网三级| 中文字幕久热精品视频在线| 亚洲成人网av| 91精品国产91久久久久福利| 欧美日韩精品在线| 91久久嫩草影院一区二区| 亚洲成人黄色网| 欧美人在线视频| 国产亚洲成av人片在线观看桃| 热re91久久精品国99热蜜臀| 欧美高清理论片| 国产91在线高潮白浆在线观看| 亚洲偷熟乱区亚洲香蕉av| 精品视频—区二区三区免费| 日韩视频免费大全中文字幕| 2018日韩中文字幕| 亚洲第一区在线观看| 国产日韩精品在线| 欧美福利小视频| 久久久久国产精品一区| 中文字幕日韩视频| 国产男人精品视频| 午夜精品99久久免费| 日韩激情视频在线| 久久久久这里只有精品| 欧美一区二区三区图| 国内精品免费午夜毛片| 亚洲sss综合天堂久久| 亚洲精品福利资源站| 欧美大片在线免费观看| 永久555www成人免费| 国产精品嫩草影院久久久| 午夜欧美大片免费观看| 久久天天躁夜夜躁狠狠躁2022| 欧美乱妇40p| 国产日韩换脸av一区在线观看| 热99久久精品| 日韩中文字幕久久| 亚洲成人精品久久| 亚洲高清不卡av|