11/12号文档资料已全面更新!;《【阿里P7】移动互联网架构师高级教程+BAT面试题》,点击下方链接前往领取:
【阿里P7】移动互联网架构师进阶高级教程+BAT面试题
本篇文章将继续从以下两个内容来介绍组件化框架设计:
- apt编译时期自动生成代码
- Android动态加载技术基础之类加载(ClassLoader)
一、apt编译时期自动生成代码
第一步
新建一个android项目。
第二步
新建立一个java的Module。注意是javalib。这个lib用来专门写注解就好。
这个lib里面就先放一个注解,叫TestAnno。
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.CLASS)
@Target(ElementType.TYPE)
public @interface TestAnno {
}
RetentionPolicy.CLASS表示编译时候注解。你需要关系的就是@Target(ElementType.TYPE)这个type是类的注解,可以有方法的,属性的等等。
然后这个javalib的gradle文件要这么写。
apply plugin: 'java'
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
}
sourceCompatibility = "1.7"
targetCompatibility = "1.7"
注解库弄好了,在弄新建一个java lib 叫inject_comiler。这个是就是核心代码了,在编译时候,执行这个个库里面的代码,然后 生成代码。这个工程 三个类。一个是注解注解处理器的核心。一个是定义生成java文件的,方法拼接。还有一个就是常量包名类名了。
先看这个的gradle文件。
apply plugin: 'java'
sourceCompatibility = "1.7"
targetCompatibility = "1.7"
dependencies {
compile fileTree(include: ['*.jar'], dir: 'libs')
compile 'com.google.auto.service:auto-service:1.0-rc2'//谷歌的帮助我们快速实现注解处理器
compile project(':inject_annotation')//自己定义的注解的java lib
compile 'com.squareup:javapoet:1.7.0'//用来生成java文件的,避免字符串拼接的尴尬
}
//这个注解是谷歌提供了,快速实现注解处理器,会帮你生成配置文件啥的 。直接用就好
@AutoService(Processor.class)
public class ActivityInjectProcesser extends AbstractProcessor {
private Filer mFiler; //文件相关的辅助类
private Elements mElementUtils; //元素相关的辅助类 许多元素
private Messager mMessager; //日志相关的辅助类
private Map<String, AnnotatedClass> mAnnotatedClassMap;
@Override
public synchronized void init(ProcessingEnvironment processingEnv) {
super.init(processingEnv);
mFiler = processingEnv.getFiler();
mElementUtils = processingEnv.getElementUtils();
mMessager = processingEnv.getMessager();
mAnnotatedClassMap = new TreeMap<>();
}
//这个方法是核心方法,在这里处理的你的业务。检测类别参数,生成java文件等
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
mAnnotatedClassMap.clear();
try {
processActivityCheck(roundEnv);
} catch (Exception e) {
e.printStackTrace();
error(e.getMessage());
}
for (AnnotatedClass annotatedClass : mAnnotatedClassMap.values()) {
try {
annotatedClass.generateActivityFile().writeTo(mFiler);
} catch (Exception e) {
error("Generate file failed, reason: %s", e.getMessage());
}
}
return true;
}
private void processActivityCheck(RoundEnvironment roundEnv) throws IllegalArgumentException, ClassNotFoundException {
//check ruleslass forName(String className
for (Element element : roundEnv.getElementsAnnotatedWith((Class<? extends Annotation>) Class.forName(TypeUtil.ANNOTATION_PATH))) {
if (element.getKind() == ElementKind.CLASS) {
getAnnotatedClass(element);
} else
error("ActivityInject only can use in ElementKind.CLASS");
}
}
private AnnotatedClass getAnnotatedClass(Element element) {
// tipe . can not use chines so ....
// get TypeElement elemen