directorio
- La interacción entre los módulos
- introducción y el uso de APT
- APT de orden superior JavaPoet uso
La interacción entre los módulos
modo interactivo común
1) EventBus-uno de comunicaciones, objeto causa de la haba pandemia del
2) que refleja el mayor costo de la tecnología de mantenimiento, parece probable alta versión limitada a @hide
3) implícitos mayores costos de mantenimiento intención, la acción es más difícil de mantener
4) la necesidad de difusión dinámica 7,0 firmar
5) cargador de clases requiere la ruta completa de la clase
soluciones
el modo de carga de clases
public void jumpApp(View v){
try {
//通过全类名的方式进行跳转
Class<?> clzz = Class.forName("com.canjun.myapplication.MainActivity");
Intent intent = new Intent(this,clzz);
startActivity(intent);
}catch (Exception e){
}
}
mapa global del modo de grabación
-
Añadir una clase de récord mundial en un módulo común (módulo común)
/** * RecorderPathManager * 记录全局的path信息 * * @author zfc * @date 2020-01-09 */ public class RecorderPathManager { private static Map<String, List<PathBean>> paths = new HashMap<>(); /** * 根据组名和路径名记录字节码信息 * @param groupName * @param pathName * @param clazz */ public static void joinGroup(String groupName,String pathName,Class clazz){ List<PathBean> path = paths.get(groupName); if(path==null){ //添加 path = new ArrayList<>(); paths.put(groupName,path); }else { for (PathBean p: path){ if(p.getPath().equals(pathName)){ return; } } } path.add(new PathBean(pathName,clazz)); } /** * 获取目标字节码对象 * @param groupName 组名 * @param pathName 路径名 * @return */ public static Class getTargetClass(String groupName,String pathName){ List<PathBean> path = paths.get(groupName); if(path==null){ return null; } for (PathBean p: path){ if(p.getPath().equals(pathName)){ return p.getClzz(); } } return null; } } /** * PathBean * * 记录Activity字节码及其路径 * 例如 * path:'order/OrderMainActivity' * clzz: OrderMainActivity.class * * @author zfc * @date 2020-01-09 */ public class PathBean { private String path; private Class clzz; public PathBean(String path, Class clzz) { this.path = path; this.clzz = clzz; } public String getPath() { return path; } public void setPath(String path) { this.path = path; } public Class getClzz() { return clzz; } public void setClzz(Class clzz) { this.clzz = clzz; } }
-
Cuando se inicia la aplicación, las necesidades de objetos complemento de código de bytes que se registrarán
/** * MyApp * * @author zfc * @date 2020-01-09 */ public class MyApp extends BaseApplication { @Override public void onCreate() { super.onCreate(); //注册activity RecorderPathManager.joinGroup("app","MainActivity",MainActivity.class); RecorderPathManager.joinGroup("order","OrderMainActivity", OrderMainActivity.class); RecorderPathManager.joinGroup("personal","PersonalMainActivity", PersonalMainActivity.class); } }
-
Cuando la página de destino del salto de código de bytes
try { Class<?> clzz = RecorderPathManager.getTargetClass("app","MainActivity"); Intent intent = new Intent(this, clzz); startActivity(intent); }catch (Exception e){ }
introducción y el uso de APT
Lo que es APT
las estructuras del lenguaje
Clasificación elemento de lenguaje
API común
Uso básico APT
-
Descripción del Medio Ambiente
a. Crear una biblioteca de Java llamado compilador
b. Añadir el compilador dependencia
// 注册注解,并对其生成META-INF的配置信息,rc2在gradle5.0后有坑 // As-3.2.1 + gradle4.10.1-all + auto-service:1.0-rc2 // implementation 'com.google.auto.service:auto-service:1.0-rc2' // As-3.4.1 + gradle5.1.1-all + auto-service:1.0-rc4 compileOnly'com.google.auto.service:auto-service:1.0-rc4' annotationProcessor'com.google.auto.service:auto-service:1.0-rc4' implementation project(':annotation')
-
La creación de procesador de anotación
/* * 通过autoService通过生成文件 */ @AutoService(Processor.class) @SupportedAnnotationTypes({"com.canjun.annotation.ARouter"}) @SupportedSourceVersion(SourceVersion.RELEASE_7) @SupportedOptions({"content"}) //外部传入的参数 public class ARouterProcessor extends AbstractProcessor { /** * 操作Element的工具类 */ private Elements elementUtils; /** * 类信息工具类 */ private Types typesUtils; /** * 日志信息输出工具类 */ private Messager messager; /** * 文件生成器 */ private Filer filer; //初始化工作 @Override public synchronized void init(ProcessingEnvironment processingEnv) { super.init(processingEnv); elementUtils = processingEnv.getElementUtils(); typesUtils = processingEnv.getTypeUtils(); messager = processingEnv.getMessager(); filer = processingEnv.getFiler(); //可以获取外部模块传入的参数 //传参方式见下小结 String content = processingEnv.getOptions().get("content"); messager.printMessage(Diagnostic.Kind.NOTE,content); } // // //需要处理的注解类型 // @Override // public Set<String> getSupportedAnnotationTypes() { // return super.getSupportedAnnotationTypes(); // } // // //jdk版本去编辑 // @Override // public SourceVersion getSupportedSourceVersion() { // return super.getSupportedSourceVersion(); // } // // //接收外部参数 // @Override // public Set<String> getSupportedOptions() { // return super.getSupportedOptions(); // } @Override public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { }
-
Pasar parámetros a la biblioteca de Java compilador AndroidModule
// 在gradle文件中配置选项参数值(用于APT传参接收) // 切记:必须写在defaultConfig节点下 javaCompileOptions { annotationProcessorOptions { arguments = [content : 'hello apt'] } }
-
procesador anotación uso AndroidModule
a.gradle comunicado la dependencia
implementation project(':annotation') //使用注解处理器 annotationProcessor project(':compiler')
anotaciones uso b.Activity
@ARouter(path="/app/MainActivity") public class MainActivity extends AppCompatActivity { ... ... }
-
Implementación del método Notas de núcleo de procesamiento
@Override public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { if(annotations == null){ return false; } messager.printMessage(Diagnostic.Kind.NOTE,annotations.toString()); //获取被注解的类对象 Set<? extends Element> elements = roundEnv.getElementsAnnotatedWith(ARouter.class); for (Element e:elements){ //获取包名 String pkgName = elementUtils.getPackageOf(e).getQualifiedName().toString(); //获取类名 String className = e.getSimpleName().toString(); messager.printMessage(Diagnostic.Kind.NOTE,pkgName + ">>" + className); //生成ARouter文件 String finalClassName = className+"$$ARouter"; try { JavaFileObject sourceFile = filer.createSourceFile(pkgName+"."+finalClassName); Writer writer = sourceFile.openWriter(); //设置包名 writer.write("package "+pkgName + ";\n"); writer.write("public class "+finalClassName+" {\n"); writer.write("public static Class<?> findTargetClass(String pathName){\n"); //获取注解的path的value(注意) String path = e.getAnnotation(ARouter.class).path(); writer.write("if(pathName.equalsIgnoreCase(\""+path+"\")){\n"); writer.write("return "+className+".class;\n"); writer.write("}\n"); writer.write("return null;\n"); writer.write("}\n"); writer.write("}\n"); writer.close(); } catch (Exception ex) { ex.printStackTrace(); } } return true; }
-
procesador Verificación genera clase de anotación
Por acumulación> Crear proyecto
anotaciones AutoService utilizando el procesador de anotación generar la información de registro de localización en la siguiente figura.
el uso de APT y de orden superior JavaPoet
JavaPoet general
JavaPoet oficial a la dirección
Lo que es JavaPoet
entorno operativo JavaPoet
implementation 'com.squareup:javapoet:1.9.0'
// 注册注解,并对其生成META-INF的配置信息,rc2在gradle5.0后有坑
// As-3.2.1 + gradle4.10.1-all + auto-service:1.0-rc2
// implementation 'com.google.auto.service:auto-service:1.0-rc2'
// As-3.4.1 + gradle5.1.1-all + auto-service:1.0-rc4
compileOnly'com.google.auto.service:auto-service:1.0-rc4'
annotationProcessor'com.google.auto.service:auto-service:1.0-rc4'
JavaPoet clase comúnmente usada
cadena de formato javaPoet
uso javaPoet
Código necesario para generar el siguiente formato
package com.canjun.myapplication;
public class MainActivity$$ARouter {
public static Class findTargetClass(String name){
if(name.equalsIgnoreCase("/app/MainActivity")){
return MainActivity.class;
}
return null;
}
}
javaPoet escrito de la siguiente manera:
@AutoService(Processor.class)
@SupportedAnnotationTypes({"com.canjun.annotation.ARouter"})
@SupportedSourceVersion(SourceVersion.RELEASE_7)
@SupportedOptions({"content"})
public class ARouterProcessor extends AbstractProcessor {
private Elements elementUtils;
private Types typeUtils;
private Messager messager;
private Filer filer;
@Override
public synchronized void init(ProcessingEnvironment processingEnv) {
super.init(processingEnv);
elementUtils = processingEnv.getElementUtils();
typeUtils = processingEnv.getTypeUtils();
messager = processingEnv.getMessager();
filer = processingEnv.getFiler();
Map<String, String> options = processingEnv.getOptions();
String content = options.get("content");
messager.printMessage(Diagnostic.Kind.NOTE, content);
}
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
if(annotations==null||annotations.isEmpty()){
return false;
}
//获取被ARouter注解的类
Set<? extends Element> elements = roundEnv.getElementsAnnotatedWith(ARouter.class);
for (Element e : elements){
//获取e的包名
String pkgName = elementUtils.getPackageOf(e).getQualifiedName().toString();
//获取类名
String className = e.getSimpleName().toString();
String newFileName = className+"$$ARouter";
//通过javaPoet写新生成的文件
//javaPoet项目地址https://github.com/square/javapoet
try {
String pathName = e.getAnnotation(ARouter.class).path();
MethodSpec methodSpec = MethodSpec.methodBuilder("findTargetClass")
.addModifiers(Modifier.PUBLIC, Modifier.STATIC)
.returns(Class.class)
.addParameter(String.class, "name")
//需要注意的是 语句中的参数 不需要显式添加“;”
.addStatement(" if(name.equalsIgnoreCase($S)){\n" +
" return $T.class;\n" +
" }\n" +
" return null", pathName, ClassName.get((TypeElement)e))
.build();
TypeSpec typeSpec = TypeSpec.classBuilder(newFileName)
.addModifiers(Modifier.PUBLIC, Modifier.FINAL)
.addMethod(methodSpec)
.build();
JavaFile javaFile = JavaFile.builder(pkgName,typeSpec)
.build();
javaFile.writeTo(filer);
} catch (IOException ex) {
ex.printStackTrace();
}
}
return true;
}
}
Generar resultados: