ARouter使用自定义注解处理器,自动生成跳转Activity的代码,避免手动填写和管理path
Posted guangdeshishe
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ARouter使用自定义注解处理器,自动生成跳转Activity的代码,避免手动填写和管理path相关的知识,希望对你有一定的参考价值。
大家都知道ARouter要跳转目标Activity需要两步:
1.在Activity上添加Route
注解
// Add annotations on pages that support routing (required)
// The path here needs to pay attention to need at least two levels : /xx/xx
@Route(path = "/test/activity")
public class YourActivity extend Activity
...
2.执行ARouter.getInstance().build("/test/activity").navigation()
方法即可实现跳转
// 1. Simple jump within application (Jump via URL in 'Advanced usage')
ARouter.getInstance().build("/test/activity").navigation();
// 2. Jump with param bundle
ARouter.getInstance().build("/test/1")
.withBundle("key1", bundle)
.navigation();
这就导致了我们需要去管理大量的path字符串,为什么ARouter不能在编译时期帮我们生成一个中间类去管理这些path字符串呢?
既然官方不支持那就自己来做一个吧,整体思路如下:
1.定义两个Activity并添加Route
注解
@Route(path = "/login/LoginActivity")
class LoginActivity : AppCompatActivity()
@Route(path = "/login/RegisterActivity")
class RegisterActivity :BaseActivity()
2.通过自定义注解处理器,处理所有带Route
注解的类,并取出注解里的path
变量值,生成一个中间类用于管理所有的path
,并封装跳转的方法,生成的中间类如下:
package com.agilezhu.processor.generate;
import android.os.Bundle;
import java.lang.String;
public final class ARouterPage
LoginActivity LoginActivity;
RegisterActivity RegisterActivity;
public ARouterPage()
LoginActivity.path = "/login/LoginActivity";
RegisterActivity.path = "/login/RegisterActivity";
public static class LoginActivity
public static String path;
static
path= "/login/LoginActivity";
public static void navigation(String key, Bundle params)
com.alibaba.android.arouter.launcher.ARouter.getInstance().build(path).withBundle(key,params).navigation();
public static void navigation()
com.alibaba.android.arouter.launcher.ARouter.getInstance().build(path).navigation();
public static class RegisterActivity
public static String path;
static
path= "/login/RegisterActivity";
public static void navigation(String key, Bundle params)
com.alibaba.android.arouter.launcher.ARouter.getInstance().build(path).withBundle(key,params).navigation();
public static void navigation()
com.alibaba.android.arouter.launcher.ARouter.getInstance().build(path).navigation();
3.使用方法
//不带参数
ARouterPage.LoginActivity.navigation()
//带Bundle类型参数
ARouterPage.RegisterActivity.navigation("params",Bundle())
//也可以使用原有ARouter跳转方式携带各种参数
ARouter.getInstance().build(ARouterPage.LoginActivity.path).withBoolean("key",true).navigation();
有了注解处理器相当于自动帮我们生成了一个管理所有path的类:
- 可以通过类似调用目标Activity的方式进行跳转;
- 简化了ARouter跳转Acticity的代码;
- 每次添加、修改、删除对应的类,都不需要手动修改管理类代码;
注解处理器开发过程
-
添加一个java 类型Module
-
build.gradle
内容如下:plugins id 'java-library' dependencies implementation fileTree(dir: 'libs', include: ['*.jar']) annotationProcessor 'com.google.auto.service:auto-service:1.0-rc7'//auto-service本身也是个注解处理器 implementation 'com.google.auto.service:auto-service:1.0-rc7'//注解 processor 类,并对其生成 META-INF 的配置信息 implementation 'com.squareup:javapoet:1.13.0' //通过类调用的形式来生成java代码,避免手动拼接字符串 implementation "com.alibaba:arouter-annotation:1.0.6" java sourceCompatibility = JavaVersion.VERSION_1_7 targetCompatibility = JavaVersion.VERSION_1_7
-
注解处理器核心类:
package com.agilezhu.processor; import com.alibaba.android.arouter.facade.annotation.Route; import com.google.auto.service.AutoService; import com.squareup.javapoet.ClassName; import com.squareup.javapoet.CodeBlock; import com.squareup.javapoet.JavaFile; import com.squareup.javapoet.MethodSpec; import com.squareup.javapoet.TypeSpec; import java.util.LinkedHashSet; import java.util.Set; import javax.annotation.processing.AbstractProcessor; import javax.annotation.processing.Filer; import javax.annotation.processing.Messager; import javax.annotation.processing.ProcessingEnvironment; import javax.annotation.processing.Processor; import javax.annotation.processing.RoundEnvironment; import javax.lang.model.SourceVersion; import javax.lang.model.element.Element; import javax.lang.model.element.Modifier; import javax.lang.model.element.TypeElement; import javax.lang.model.util.Elements; import javax.tools.Diagnostic; /** * Generate ARouterPage.java for ARouter */ @AutoService(Processor.class) public class ARouterProcessor extends AbstractProcessor private Filer mFiler; //文件相关工具类:用于保存生成的java类文件 private Elements mElementUtils; //元素相关工具类:用于获取java类文件 private Messager mMessager;//用于打印日志 @Override public synchronized void init(ProcessingEnvironment processingEnvironment) super.init(processingEnvironment); mFiler = processingEnv.getFiler(); mElementUtils = processingEnv.getElementUtils(); mMessager = processingEnv.getMessager(); @Override public Set<String> getSupportedAnnotationTypes() //返回该注解处理器能够处理哪些注解 Set<String> types = new LinkedHashSet<>(); types.add(Route.class.getName()); return types; @Override public SourceVersion getSupportedSourceVersion() //返回当前注解处理器支持的java版本号 return SourceVersion.latest(); @Override public boolean process(Set<? extends TypeElement> set, RoundEnvironment roundEnvironment) if (set == null || set.size() == 0) return false; //将要生成的java完整类名 String targetClassName = "ARouterPage"; String packageName = "com.agilezhu.processor.generate"; //创建方法(构造方法) MethodSpec.Builder bindMethodBuilder = MethodSpec.methodBuilder("<init>") .addModifiers(Modifier.PUBLIC); //创建类 TypeSpec.Builder aRouterPageClassBuilder = TypeSpec.classBuilder(targetClassName) .addModifiers(Modifier.PUBLIC, Modifier.FINAL); //获取所有的源码文件 Set<? extends Element> elements = roundEnvironment.getRootElements(); for (Element element : elements) if (!(element instanceof TypeElement)) //判断是否class类 continue; //转换成class类型 TypeElement typeElement = (TypeElement) element; //当前文件的类名 String classSimpleName = element.getSimpleName().toString(); Route routeAnnotation = element.getAnnotation(Route.class); if (routeAnnotation == null) continue; mMessager.printMessage(Diagnostic.Kind.WARNING, "myProcess=====>>>>>" + classSimpleName); ClassName innerClassName = ClassName.get(packageName, targetClassName, classSimpleName); try aRouterPageClassBuilder.addField(innerClassName, classSimpleName) .addType(TypeSpec.classBuilder(innerClassName.simpleName()) .addModifiers(Modifier.STATIC, Modifier.PUBLIC) .addField(String.class, "path", Modifier.PUBLIC, Modifier.STATIC) .addStaticBlock(CodeBlock.builder().addStatement("path= \\"" + routeAnnotation.path() + "\\"").build()) .addMethod(MethodSpec .methodBuilder("navigation") .addParameter(String.class,"key") .addParameter(ClassName.get("android.os","Bundle"), "params") .addStatement("com.alibaba.android.arouter.launcher.ARouter.getInstance().build(path).withBundle(key,params).navigation()") .addModifiers(Modifier.PUBLIC, Modifier.STATIC) .build()) .addMethod(MethodSpec .methodBuilder("navigation") .addStatement("com.alibaba.android.arouter.launcher.ARouter.getInstance().build(path).navigation()") .addModifiers(Modifier.PUBLIC, Modifier.STATIC) .build()) .build()); catch (Exception e) e.printStackTrace(); //构造方法中添加初始化代码 bindMethodBuilder.addStatement(classSimpleName + ".path = \\"" + routeAnnotation.path() + "\\""); aRouterPageClassBuilder.addMethod(bindMethodBuilder.build()); //创建java文件 JavaFile bindProxyFile = JavaFile .builder(packageName, aRouterPageClassBuilder.build()) .build(); try //保存java类文件 bindProxyFile.writeTo(mFiler); catch (Throwable e) e.printStackTrace(); return false;
-
业务模块中引用:
kapt project(path: ':lib:processor') //这里用的kapt处理Kotlin代码
-
重新编译后,在当前模块
build/generated/source/kapt/debug/com/agilezhu/processor/generate/ARouterPage.java
路径下就能看到生成的类
以上是关于ARouter使用自定义注解处理器,自动生成跳转Activity的代码,避免手动填写和管理path的主要内容,如果未能解决你的问题,请参考以下文章