5、路由信息分组
每个路由信息都有一个分组 , 在定义 Route 注解时 , 分组为 “” 空字符串 ;
@Target({ElementType.TYPE}) @Retention(RetentionPolicy.CLASS) public @interface Route { /** * 路由路径, 标识一个路由节点 * 该字段没有默认值, 必须设置 * @return */ String path(); /** * 路由分组, 默认为空, 选择性设置 * 路由节点可以按照分组进行加载 * @return */ String group() default ""; }
根据设置的路由路径 , @Route(path = “/app/MainActivity”) 中的 “/app/MainActivity” , 将其中的 app 作为路由分组 ;
截取路由地址 “/app/MainActivity” 中前两个斜线之间字符串作为路由分组 ;
/** * 验证路由地址 * @Route(path = "/app/MainActivity") * @param routeBean */ private void checkRouteAddress(RouteBean routeBean){ // 获取路由地址 String routeAddress = routeBean.getRouteAddress(); // 获取路由分组 String routeGroup = routeBean.getRouteGroup(); // 验证路由地址是否以 "/" 开头 if (!routeAddress.startsWith("/")) { throw new RuntimeException("路由地址 " + routeAddress + " 格式错误"); } // 如果路由地址的分组为空 , // 则截取第 0 和 第 1 个 "/" 之间的字符串作为分组名称 if (routeGroup == null || "".equals(routeGroup)){ String group = routeAddress.substring( routeAddress.indexOf("/", 0) + 1, routeAddress.indexOf("/", 1) ); if (group == null || "".equals(group)){ throw new RuntimeException("路由地址 " + routeAddress + " 获取分组错误"); } // 打印组名 mMessager.printMessage(Diagnostic.Kind.NOTE, "打印路由地址 " + routeAddress + " 的组名为 " + group); // 正式设置路由地址分组 routeBean.setRouteGroup(group); } }
三、完整的 注解处理器 代码
完整的 注解处理器 代码 :
package kim.hsl.router_compiler; import com.google.auto.service.AutoService; import java.util.Map; 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.annotation.processing.SupportedAnnotationTypes; import javax.annotation.processing.SupportedOptions; import javax.annotation.processing.SupportedSourceVersion; import javax.lang.model.SourceVersion; import javax.lang.model.element.Element; import javax.lang.model.element.TypeElement; import javax.lang.model.type.TypeMirror; import javax.lang.model.util.Elements; import javax.lang.model.util.Types; import javax.tools.Diagnostic; import kim.hsl.router_annotation.Route; import kim.hsl.router_annotation.model.RouteBean; // 注解处理器接收的参数 @SupportedOptions("moduleName") // 自动注册注解处理器 @AutoService(Processor.class) // 支持的注解类型 @SupportedAnnotationTypes({"kim.hsl.router_annotation.Route"}) // 支持的 Java 版本 @SupportedSourceVersion(SourceVersion.RELEASE_8) public class RouterProcessor extends AbstractProcessor { /** * 注解处理器中使用 Messager 对象打印日志 */ private Messager mMessager; /** * 用于写出生成的 Java 代码 */ private Filer mFiler; /** * 注解节点工具 */ private Elements mElementUtils; /** * 类工具 */ private Types mTypeUtils; /** * 获取的 moduleName 参数 */ private String mModuleName; /** * 该函数在初始化时调用 , 相当于构造函数 * @param processingEnvironment */ @Override public synchronized void init(ProcessingEnvironment processingEnvironment) { super.init(processingEnvironment); // 获取打印日志接口 this.mMessager = processingEnvironment.getMessager(); // 测试日志打印 mMessager.printMessage(Diagnostic.Kind.NOTE, "Messager Print Log"); this.mFiler = processingEnvironment.getFiler(); this.mElementUtils = processingEnvironment.getElementUtils(); this.mTypeUtils = processingEnvironment.getTypeUtils(); // 获取 moduleName 参数 // 先获取 注解处理器 选项 Map<String, String> options = processingEnvironment.getOptions(); if (options != null){ mModuleName = options.get("moduleName"); mMessager.printMessage(Diagnostic.Kind.NOTE, "打印 moduleName 参数 : " + mModuleName); } } /** * 该函数在注解处理器注册时自动执行, 是处理注解的核心函数 * * Set<? extends TypeElement> set 参数 : 该集合表示使用了相关注解的节点的集合 * * @param set * @param roundEnvironment * @return */ @Override public boolean process(Set<? extends TypeElement> set, RoundEnvironment roundEnvironment) { if (set == null || set.isEmpty()){ // 如果没有检测到注解 , 直接退出 return false; } // 获取被 @Route 注解的节点 // 这些 注解节点 都是类节点 , TypeElement 类型的 Set<? extends Element> routeElements = roundEnvironment.getElementsAnnotatedWith(Route.class); generateRouteClass(routeElements); return false; } private void generateRouteClass(Set<? extends Element> routeElements) { // 获取 android.app.Activity 类型的注解节点 TypeElement activityElement = mElementUtils.getTypeElement("android.app.Activity"); // 处理 @Route(path = "app/MainActivity") 节点 for (Element element : routeElements) { // 获取 Route 注解 Route route = element.getAnnotation(Route.class); // 路由表中的单个路由对象 RouteBean routeBean = null; // 打印类节点全类名 mMessager.printMessage(Diagnostic.Kind.NOTE, "打印类节点 typeElement : " + activityElement.getQualifiedName()); // 判断 typeMirror 注解节点是否是 Activity 类型 if (mTypeUtils.isSubtype(element.asType(), activityElement.asType())) { // 该节点是 android.app.Activity 类型的 routeBean = new RouteBean( RouteBean.Type.ACTIVITY, // 路由对象类型 element, // 路由节点 null, // 类对象 route.path(), // 路由地址 route.group()); // 路由组 // 检查路由地址 checkRouteAddress(routeBean); // 打印路由信息 mMessager.printMessage(Diagnostic.Kind.NOTE, "打印路由信息 : " + routeBean.toString()); }else{ // 该节点不是 android.app.Activity 类型的 throw new RuntimeException("@Route 注解节点类型错误"); } } } /** * 验证路由地址 * @Route(path = "/app/MainActivity") * @param routeBean */ private void checkRouteAddress(RouteBean routeBean){ // 获取路由地址 String routeAddress = routeBean.getRouteAddress(); // 获取路由分组 String routeGroup = routeBean.getRouteGroup(); // 验证路由地址是否以 "/" 开头 if (!routeAddress.startsWith("/")) { throw new RuntimeException("路由地址 " + routeAddress + " 格式错误"); } // 如果路由地址的分组为空 , // 则截取第 0 和 第 1 个 "/" 之间的字符串作为分组名称 if (routeGroup == null || "".equals(routeGroup)){ String group = routeAddress.substring( routeAddress.indexOf("/", 0) + 1, routeAddress.indexOf("/", 1) ); if (group == null || "".equals(group)){ throw new RuntimeException("路由地址 " + routeAddress + " 获取分组错误"); } // 打印组名 mMessager.printMessage(Diagnostic.Kind.NOTE, "打印路由地址 " + routeAddress + " 的组名为 " + group); // 正式设置路由地址分组 routeBean.setRouteGroup(group); } } }
执行结果 :
注: Messager Print Log 注: 打印 moduleName 参数 : app 注: 打印类节点 typeElement : android.app.Activity 注: 打印路由地址 /app/MainActivity 的组名为 app 注: 打印路由信息 : RouteBean{type=ACTIVITY, element=kim.hsl.component.MainActivity, clazz=null, routeAddress='/app/MainActivity', routeGroup='app'}
四、博客资源
博客源码 :
GitHub : https://github.com/han1202012/Component
CSDN 下载 :