安卓AOP三剑客之Android APT技术浅谈

简介:

通过学习与使用square公司的开源项目javapoet,来实现仓库层动态生成代码

Android APT技术浅谈

安卓AOP三剑客: APT, AspectJ, Javassist

Android APT技术浅谈

Android APT

APT(Annotation Processing Tool 的简称),可以在代码编译期解析注解,并且生成新的 Java 文件,减少手动的代码输入。现在有很多主流库都用上了 APT,比如 Dagger2, ButterKnife, EventBus3 等

代表框架:

  • DataBinding
  • Dagger2
  • ButterKnife
  • EventBus3
  • DBFlow
  • AndroidAnnotation

使用姿势

1,在android工程中,创建一个java的Module,写一个类继承AbstractProcessor


 
 
  1. @AutoService(Processor.class) // javax.annotation.processing.IProcessor 
  2. @SupportedSourceVersion(SourceVersion.RELEASE_7) //java 
  3. @SupportedAnnotationTypes({ // 标注注解处理器支持的注解类型 
  4.     "com.annotation.SingleDelegate"
  5.     "com.annotation.MultiDelegate" 
  6. }) 
  7. public class AnnotationProcessor extends AbstractProcessor { 
  8.  
  9. public static final String PACKAGE = "com.poet.delegate"
  10. public static final String CLASS_DESC = "From poet compiler"
  11.  
  12. public Filer filer; //文件相关的辅助类 
  13. public Elements elements; //元素相关的辅助类 
  14. public Messager messager; //日志相关的辅助类 
  15. public Types types; 
  16.  
  17. @Override 
  18. public boolean process(Set<? extends TypeElement> set, RoundEnvironment roundEnvironment) { 
  19.     filer = processingEnv.getFiler(); 
  20.     elements = processingEnv.getElementUtils(); 
  21.     messager = processingEnv.getMessager(); 
  22.     types = processingEnv.getTypeUtils(); 
  23.  
  24.     new SingleDelegateProcessor().process(set, roundEnvironment, this); 
  25.     new MultiDelegateProcessor().process(set, roundEnvironment, this); 
  26.  
  27.     return true

2,在继承AbstractProcessor类中的process方法,处理我们自定义的注解,生成代码:


 
 
  1. public class SingleDelegateProcessor implements IProcessor {  
  2. @Override 
  3. public void process(Set<? extends TypeElement> set, RoundEnvironment roundEnv, 
  4.                 AnnotationProcessor abstractProcessor) { 
  5. // 查询注解是否存在 
  6. Set<? extends Element> elementSet = 
  7.         roundEnv.getElementsAnnotatedWith(SingleDelegate.class); 
  8. Set<TypeElement> typeElementSet = ElementFilter.typesIn(elementSet); 
  9. if (typeElementSet == null || typeElementSet.isEmpty()) { 
  10.     return
  11.  
  12. // 循环处理注解 
  13. for (TypeElement typeElement : typeElementSet) { 
  14.     if (!(typeElement.getKind() == ElementKind.INTERFACE)) { // 只处理接口类型 
  15.         continue
  16.     } 
  17.  
  18.     // 处理 SingleDelegate,只处理 annotation.classNameImpl() 不为空的注解 
  19.     SingleDelegate annotation = typeElement.getAnnotation(SingleDelegate.class); 
  20.     if ("".equals(annotation.classNameImpl())) { 
  21.         continue
  22.     } 
  23.     Delegate delegate = annotation.delegate(); 
  24.  
  25.     // 添加构造器 
  26.     MethodSpec.Builder constructorBuilder = MethodSpec.constructorBuilder() 
  27.             .addModifiers(Modifier.PUBLIC); 
  28.  
  29.     // 创建类名相关 class builder 
  30.     TypeSpec.Builder builder = 
  31.             ProcessUtils.createTypeSpecBuilder(typeElement, annotation.classNameImpl()); 
  32.  
  33.     // 处理 delegate 
  34.     builder = ProcessUtils.processDelegate(typeElement, builder, 
  35.             constructorBuilder, delegate); 
  36.  
  37.     // 检查是否继承其它接口 
  38.     builder = processSuperSingleDelegate(abstractProcessor, builder, constructorBuilder, typeElement); 
  39.  
  40.     // 完成构造器 
  41.     builder.addMethod(constructorBuilder.build()); 
  42.  
  43.     // 创建 JavaFile 
  44.     JavaFile javaFile = JavaFile.builder(AnnotationProcessor.PACKAGE, builder.build()).build(); 
  45.     try { 
  46.         javaFile.writeTo(abstractProcessor.filer); 
  47.     } catch (IOException e) { 
  48.         e.printStackTrace(); 
  49.     } 

3,在项目Gradle中添加 annotationProcessor project 引用


 
 
  1. compile project(':apt-delegate-annotation' 
  2. annotationProcessor project(':apt-delegate-compiler'

4,如果有自定义注解的话,创建一个java的Module,专门放入自定义注解。项目与apt Module都需引用自定义注解Module

4-1,主工程:


 
 
  1. compile project(':apt-delegate-annotation' 
  2. annotationProcessor project(':apt-delegate-compiler'

4-2,apt Module:


 
 
  1. compile project(':apt-delegate-annotation' 
  2. compile 'com.google.auto.service:auto-service:1.0-rc2' 
  3. compile 'com.squareup:javapoet:1.4.0' 

5,生成的源代码在build/generated/source/apt下可以看到

Android APT技术浅谈

难点

就apt本身来说没有任何难点可言,难点一在于设计模式和解耦思想的灵活应用,二在与代码生成的繁琐,你可以手动字符串拼接,当然有更高级的玩法用squareup的javapoet,用建造者的模式构建出任何你想要的源代码

优点

它的强大之处无需多言,看代表框架的源码,你可以学到很多新姿势。总的一句话:它可以做任何你不想做的繁杂的工作,它可以帮你写任何你不想重复代码。懒人福利,老司机必备神技,可以提高车速,让你以任何姿势漂移。它可以生成任何源代码供你在任何地方使用,就像剑客的剑,快疾如风,无所不及

我想稍微研究一下,APT还可以在哪些地方使用,比如:Repository层?

APT在Repository层的尝试

了解APT与简单学习之后,搭建Repository层时,发现有一些简单,重复模版的代码

每一次添加新接口都需要简单地修改很多地方,能不能把一部分代码自动生成,减少改动的次数呢?

Repository层

Android APT技术浅谈

IRemoteDataSource, RemoteDataSourceImpl

远程数据源,属于网络请求相关

ILocalDataSource, LocalDataSourceImpl

本地数据源,属于本地数据持久化相关

IRepository,RepositoryImpl

仓库代理类,代理远程数据源与本地数据源

Repository层APT设计思路

发现在具体实现类中,大多都是以代理类的形式调用:方法中调用代理对象,方法名称与参数,返回值类型都相同。显然可以进行APT的尝试

  • 简单的情况,具体实现类中只有一个代理对象
  • 复杂的情况,有多个代理对象,方法内并有一些变化

期望结果:

  • 把RemoteDataSourceImpl自动化生成
  • 把LocalDataSourceImpl自动化生成
  • 把RepositoryImpl自动化生成

自定义注解设计

要想具体实现类自动生成,首先要知道需要什么:

  • 方便自动生成java文件的类库
  • 自动生成类名字是什么
  • 需要注入的代理对象
  • 让代理对象代理的方法集

自动生成java文件的类库,可以使用 squareup javapoet

自动生成类名字,代理对象,方法集需要通过自定义注解配置参数的形成,在AbstractProcessor中获取

Delegate


 
 
  1. @Retention(RetentionPolicy.SOURCE) 
  2. @Target(ElementType.TYPE) 
  3. public @interface Delegate { 
  4.  
  5. /** 
  6.  * delegate class package 
  7.  */ 
  8. String delegatePackage(); 
  9.  
  10. /** 
  11.  * delegate class name 
  12.  */ 
  13. String delegateClassName(); 
  14.  
  15. /** 
  16.  * delegate simple name 
  17.  */ 
  18. String delegateSimpleName(); 

SingleDelegate


 
 
  1. @Retention(RetentionPolicy.SOURCE) 
  2. @Target(ElementType.TYPE) 
  3. public @interface SingleDelegate { 
  4.  
  5. /** 
  6.  * impl class name 
  7.  */ 
  8. String classNameImpl(); 
  9.  
  10. /** 
  11.  * delegate data 
  12.  */ 
  13. Delegate delegate(); 

MultiDelegate


 
 
  1. @Retention(RetentionPolicy.SOURCE) 
  2. @Target(ElementType.TYPE) 
  3. public @interface MultiDelegate {  
  4. /** 
  5.  * impl class name 
  6.  */ 
  7. String classNameImpl();  
  8. /** 
  9.  * delegate list 
  10.  */ 
  11. Delegate[] Delegates(); 

处理自定义的注解、生成代码

AnnotationProcessor


 
 
  1. @AutoService(Processor.class) // javax.annotation.processing.IProcessor 
  2. @SupportedSourceVersion(SourceVersion.RELEASE_7) //java 
  3. @SupportedAnnotationTypes({ // 标注注解处理器支持的注解类型 
  4.     "com.annotation.SingleDelegate"
  5.     "com.annotation.MultiDelegate" 
  6. }) 
  7. public class AnnotationProcessor extends AbstractProcessor {  
  8. public static final String PACKAGE = "com.poet.delegate"
  9. public static final String CLASS_DESC = "From poet compiler" 
  10. public Filer filer; //文件相关的辅助类 
  11. public Elements elements; //元素相关的辅助类 
  12. public Messager messager; //日志相关的辅助类 
  13. public Types types;  
  14. @Override 
  15. public boolean process(Set<? extends TypeElement> set, RoundEnvironment roundEnvironment) { 
  16.     filer = processingEnv.getFiler(); 
  17.     elements = processingEnv.getElementUtils(); 
  18.     messager = processingEnv.getMessager(); 
  19.     types = processingEnv.getTypeUtils(); 
  20.  
  21.     new SingleDelegateProcessor().process(set, roundEnvironment, this); 
  22.     new MultiDelegateProcessor().process(set, roundEnvironment, this); 
  23.  
  24.     return true
原文发布时间为: 2017-10-16 本文作者:佚名 本文来自云栖社区合作伙伴“51CTO”,了解相关信息可以关注。
相关文章
|
2月前
|
安全 Android开发 iOS开发
Android vs. iOS:构建生态差异与技术较量的深度剖析###
本文深入探讨了Android与iOS两大移动操作系统在构建生态系统上的差异,揭示了它们各自的技术优势及面临的挑战。通过对比分析两者的开放性、用户体验、安全性及市场策略,本文旨在揭示这些差异如何塑造了当今智能手机市场的竞争格局,为开发者和用户提供决策参考。 ###
|
2月前
|
安全 Android开发 iOS开发
安卓与iOS的较量:技术深度对比
【10月更文挑战第18天】 在智能手机操作系统领域,安卓和iOS无疑是两大巨头。本文将深入探讨这两种系统的技术特点、优势以及它们之间的主要差异,帮助读者更好地理解这两个平台的独特之处。
55 0
|
1月前
|
安全 搜索推荐 Android开发
揭秘安卓与iOS系统的差异:技术深度对比
【10月更文挑战第27天】 本文深入探讨了安卓(Android)与iOS两大移动操作系统的技术特点和用户体验差异。通过对比两者的系统架构、应用生态、用户界面、安全性等方面,揭示了为何这两种系统能够在市场中各占一席之地,并为用户提供不同的选择。文章旨在为读者提供一个全面的视角,理解两种系统的优势与局限,从而更好地根据自己的需求做出选择。
81 2
|
1月前
|
XML Java 开发者
论面向方面的编程技术及其应用(AOP)
【11月更文挑战第2天】随着软件系统的规模和复杂度不断增加,传统的面向过程编程和面向对象编程(OOP)在应对横切关注点(如日志记录、事务管理、安全性检查等)时显得力不从心。面向方面的编程(Aspect-Oriented Programming,简称AOP)作为一种新的编程范式,通过将横切关注点与业务逻辑分离,提高了代码的可维护性、可重用性和可读性。本文首先概述了AOP的基本概念和技术原理,然后结合一个实际项目,详细阐述了在项目实践中使用AOP技术开发的具体步骤,最后分析了使用AOP的原因、开发过程中存在的问题及所使用的技术带来的实际应用效果。
61 5
|
1月前
|
安全 搜索推荐 Android开发
揭秘iOS与安卓系统的差异:一场技术与哲学的较量
在智能手机的世界里,iOS和Android无疑是两大巨头,它们不仅定义了操作系统的标准,也深刻影响了全球数亿用户的日常生活。本文旨在探讨这两个平台在设计理念、用户体验、生态系统及安全性等方面的本质区别,揭示它们背后的技术哲学和市场策略。通过对比分析,我们将发现,选择iOS或Android,不仅仅是选择一个操作系统,更是选择了一种生活方式和技术信仰。
|
2月前
|
安全 Android开发 iOS开发
iOS与安卓:技术生态的双雄争霸
在当今数字化时代,智能手机操作系统的竞争愈发激烈。iOS和安卓作为两大主流平台,各自拥有独特的技术优势和市场地位。本文将从技术架构、用户体验、安全性以及开发者支持四个方面,深入探讨iOS与安卓之间的差异,并分析它们如何塑造了今天的移动技术生态。无论是追求极致体验的苹果用户,还是享受开放自由的安卓粉丝,了解这两大系统的内在逻辑对于把握未来趋势至关重要。
|
2月前
|
安全 搜索推荐 Android开发
揭秘iOS与Android系统的差异:一场技术与哲学的较量
在当今数字化时代,智能手机操作系统的选择成为了用户个性化表达和技术偏好的重要标志。iOS和Android,作为市场上两大主流操作系统,它们之间的竞争不仅仅是技术的比拼,更是设计理念、用户体验和生态系统构建的全面较量。本文将深入探讨iOS与Android在系统架构、应用生态、用户界面及安全性等方面的本质区别,揭示这两种系统背后的哲学思想和市场策略,帮助读者更全面地理解两者的优劣,从而做出更适合自己的选择。
|
2月前
|
安全 Android开发 iOS开发
安卓vs iOS:探索两种操作系统的独特魅力与技术深度###
【10月更文挑战第16天】 本文旨在深入浅出地探讨安卓(Android)与iOS这两种主流移动操作系统的特色、优势及背后的技术理念。通过对比分析,揭示它们各自如何塑造了移动互联网的生态,并为用户提供丰富多彩的智能体验。无论您是科技爱好者还是普通用户,都能从这篇文章中感受到技术创新带来的无限可能。 ###
58 2
|
2月前
|
机器学习/深度学习 人工智能 Android开发
安卓与iOS:技术演进的双城记
【10月更文挑战第16天】 在移动操作系统的世界里,安卓和iOS无疑是两个最重要的玩家。它们各自代表了不同的技术理念和市场策略,塑造了全球数亿用户的移动体验。本文将深入探讨这两个平台的发展历程、技术特点以及它们如何影响了我们的数字生活,旨在为读者提供一个全面而深入的视角,理解这两个操作系统背后的哲学和未来趋势。
34 2
|
2月前
|
Java Android开发 Swift
掌握安卓与iOS应用开发:技术比较与选择指南
在移动应用开发领域,谷歌的安卓和苹果的iOS系统无疑是两大巨头。它们不仅塑造了智能手机市场,还影响了开发者的日常决策。本文深入探讨了安卓与iOS平台的技术差异、开发环境及工具、以及市场表现和用户基础。通过对比分析,旨在为开发者提供实用的指导,帮助他们根据项目需求、预算限制和性能要求,做出最合适的平台选择。无论是追求高度定制的用户体验,还是期望快速进入市场,本文都将为您的开发旅程提供有价值的见解。