赞
踩
1)EventBus一对一通讯,会造成Bean对象泛
2)反射技术 维护成本较高,高版本容易出现@hide限
3)隐式意图 维护成本较高,action比较难以维护
4) 广播 7.0后需要动态注册
5)类加载器 需要全类名路径
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){
}
}
在公共模块(common模块)添加全局记录类
/** * 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; } }
在应用启动时,添加需要记录的字节码对象
/** * 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); } }
在页面跳转时,使用字节码对象
try {
Class<?> clzz = RecorderPathManager.getTargetClass("app","MainActivity");
Intent intent = new Intent(this, clzz);
startActivity(intent);
}catch (Exception e){
}
语言元素分类
常用的API
环境描述
a.创建java library 名为compiler
b.为compiler添加依赖
// 注册注解,并对其生成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')
创建注解处理器
/* * 通过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) { }
通过AndroidModule向java library compiler传入参数
// 在gradle文件中配置选项参数值(用于APT传参接收)
// 切记:必须写在defaultConfig节点下
javaCompileOptions {
annotationProcessorOptions {
arguments = [content : 'hello apt']
}
}
AndroidModule使用注解处理器
a.gradle中依赖的声明
implementation project(':annotation')
//使用注解处理器
annotationProcessor project(':compiler')
b.Activity中使用注解
@ARouter(path="/app/MainActivity")
public class MainActivity extends AppCompatActivity {
...
...
}
注解处理中核心方法的实现
@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; }
验证注解处理器生成的类
通过build->make project
使用autoService注解 注解处理器,会在如下图中的位置生成注册信息。
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'
package com.canjun.myapplication;
public class MainActivity$$ARouter {
public static Class findTargetClass(String name){
if(name.equalsIgnoreCase("/app/MainActivity")){
return MainActivity.class;
}
return null;
}
}
@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; } }
生成结果:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。