ARouter讲解3_RouteProcessor

  • path :不能为空,而且必须以 “/”开头,
  • group :可以自己设置group的值,默认在path中获取,比如 @Route(path = “/test/activity1”),在构建 RouteMeta 时就会用test作为组名。
  • name :生成文档用的
  • extras:可以带一些额外的参数
  • priority: 优先级,值越小,优先级越高

概述

通过 Route 的注解,框架会把我们注解的Activity 、Fragment、Service、ContentProvider以及IProvider收集起来

image-20210512234509772.png

按照不同的Group会生成类似这样的代码,这样框架在初始化的时候,就可以根据这些类把路由信息收集起来。

image-20210512234700592.png

详情

@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
if (CollectionUtils.isNotEmpty(annotations)) {
// 获取所有被 Route 注解的类
Set<? extends Element> routeElements = roundEnv.getElementsAnnotatedWith(Route.class);
try {=
this.parseRoutes(routeElements);
} catch (Exception e) {
logger.error(e);
}
return true;
}

return false;
}

private void parseRoutes(Set<? extends Element> routeElements) throws IOException {
if (CollectionUtils.isNotEmpty(routeElements)) {

rootMap.clear();

TypeMirror type_Activity = elementUtils.getTypeElement(ACTIVITY).asType();
TypeMirror type_Service = elementUtils.getTypeElement(SERVICE).asType();
TypeMirror fragmentTm = elementUtils.getTypeElement(FRAGMENT).asType();
TypeMirror fragmentTmV4 = elementUtils.getTypeElement(Consts.FRAGMENT_V4).asType();

// Interface of ARouter
// com.alibaba.android.arouter.facade.template.IRouteGroup
TypeElement type_IRouteGroup = elementUtils.getTypeElement(IROUTE_GROUP);
// com.alibaba.android.arouter.facade.template.IProviderGroup
TypeElement type_IProviderGroup = elementUtils.getTypeElement(IPROVIDER_GROUP);
ClassName routeMetaCn = ClassName.get(RouteMeta.class);
ClassName routeTypeCn = ClassName.get(RouteType.class);

/*
Build input type, format as :

*/
// 方法的参数类型
ParameterizedTypeName inputMapTypeOfRoot = ParameterizedTypeName.get(
ClassName.get(Map.class),
ClassName.get(String.class),
ParameterizedTypeName.get(
ClassName.get(Class.class),
WildcardTypeName.subtypeOf(ClassName.get(type_IRouteGroup))
)
);

/*

*/
// 方法的参数类型
ParameterizedTypeName inputMapTypeOfGroup = ParameterizedTypeName.get(
ClassName.get(Map.class),
ClassName.get(String.class),
ClassName.get(RouteMeta.class)
);

/*
Build input param name.
*/
// 方法的参数名
ParameterSpec rootParamSpec = ParameterSpec.builder(inputMapTypeOfRoot, “routes”).build();
ParameterSpec groupParamSpec = ParameterSpec.builder(inputMapTypeOfGroup, “atlas”).build();
ParameterSpec providerParamSpec = ParameterSpec.builder(inputMapTypeOfGroup, “providers”).build();

/*
Build method : ‘loadInto’
*/
// 构建一个方法 public void loadInto(Map<String, Class<? extends IRouteGroup>> routes)
MethodSpec.Builder loadIntoMethodOfRootBuilder = MethodSpec.methodBuilder(METHOD_LOAD_INTO)
.addAnnotation(Override.class)
.addModifiers(PUBLIC)
.addParameter(rootParamSpec);

// Follow a sequence, find out metas of group first, generate java file, then statistics them as root.
// 遍历被Route注解的类
for (Element element : routeElements) {
TypeMirror tm = element.asType();
Route route = element.getAnnotation(Route.class);
RouteMeta routeMeta;

// 构建 RouteMeta
// 因为Activity 或者 Fragment 是可以传递参数的,getIntent()、getArguments(),就收集该类中被 Autowired 注解的字段
// Activity or Fragment
if (types.isSubtype(tm, type_Activity) || types.isSubtype(tm, fragmentTm) || types.isSubtype(tm, fragmentTmV4)) {
// 当前的类是 Activity 或 Fragment

// Get all fields annotation by @Autowired
// paramsType 与 injectConfig 用来生成文档的,不用关心
Map<String, Integer> paramsType = new HashMap<>();
Map<String, Autowired> injectConfig = new HashMap<>();
//收集类中的被Autowired注解的字段,但字段不能是IProvider类型
injectParamCollector(element, paramsType, injectConfig);

if (types.isSubtype(tm, type_Activity)) {
// Activity
routeMeta = new RouteMeta(route, element, RouteType.ACTIVITY, paramsType);
} else {
// Fragment
routeMeta = new RouteMeta(route, element, RouteType.parse(FRAGMENT), paramsType);
}

routeMeta.setInjectConfig(injectConfig);
} else if (types.isSubtype(tm, iProvider)) { // IProvider
routeMeta = new RouteMeta(route, element, RouteType.PROVIDER, null);
} else if (types.isSubtype(tm, type_Service)) { // Service
routeMeta = new RouteMeta(route, element, RouteType.parse(SERVICE), null);
} else {
throw new RuntimeException(“The @Route is marked on unsupported class, look at [” + tm.toString() + “].”);
}
// 收集具有相同的group的RouteMeta到 Map<String, Set>
categories(routeMeta);
}

// 生成 loadInto 方法
// public void loadInto(Map<Integer, Class<? extends IInterceptor>> interceptors)
MethodSpec.Builder loadIntoMethodOfProviderBuilder = MethodSpec.methodBuilder(METHOD_LOAD_INTO)
.addAnnotation(Override.class)
.addModifiers(PUBLIC)
.addParameter(providerParamSpec);

// Start generate java source, structure is divided into upper and lower levels, used for demand initialization.
for (Map.Entry<String, Set> entry : groupMap.entrySet()) {

String groupName = entry.getKey();

//public void loadInto(Map<String, RouteMeta> atlas)
MethodSpec.Builder loadIntoMethodOfGroupBuilder = MethodSpec.methodBuilder(METHOD_LOAD_INTO)
.addAnnotation(Override.class)
.addModifiers(PUBLIC)
.addParameter(groupParamSpec);

// Build group method body
Set groupData = entry.getValue();
for (RouteMeta routeMeta : groupData) {

// 这个ClassName就是被Route注解的类名
ClassName className = ClassName.get((TypeElement) routeMeta.getRawType());

//这是给 IProvider 的类型做了一次特殊服务

switch (routeMeta.getType()) {
case PROVIDER: // Need cache provider’s super class
// 注意 routeMeta 返回的是RouteType类型,比如 PROVIDER类型,就是说element是 IProvider 的子类。
// 获取这个TypeElement的直接父接口
// 比如我们一般定义XXXServiceImpl, XXXService ,然后XXXService接口继承自IProvider
List<? extends TypeMirror> interfaces = ((TypeElement) routeMeta.getRawType()).getInterfaces();
// 遍历这个父接口
for (TypeMirror tm : interfaces) {

if (types.isSameType(tm, iProvider)) { // Its implements iProvider interface himself.
// This interface extend the IProvider, so it can be used for mark provider
// 该element是 IProvider的直接子类

// 就会生成类似 providers.put(“com.alibaba.android.arouter.demo.module1.testservice.SingleService”,
// RouteMeta.build(RouteType.PROVIDER, SingleService.class, “/yourservicegroupname/single”, // “yourservicegroupname”, null, -1, -2147483648));
loadIntoMethodOfProviderBuilder.addStatement(
“providers.put($S, T . b u i l d ( T.build( T.build(T.” + routeMeta.getType() + ", $T.class, $S, $S, null, " + routeMeta.getPriority() + ", " + routeMeta.getExtra() + “))”,
(routeMeta.getRawType()).toString(),
routeMetaCn,
routeTypeCn,
className,
routeMeta.getPath(),
routeMeta.getGroup());

} else if (types.isSubtype(tm, iProvider)) {

// This interface extend the IProvider, so it can be used for mark provider
// 类似这样 providers.put(“com.alibaba.android.arouter.demo.service.HelloService”,
// RouteMeta.build(RouteType.PROVIDER, HelloServiceImpl.class, “/yourservicegroupname/hello”,
// “yourservicegroupname”, null, -1, -2147483648));

loadIntoMethodOfProviderBuilder.addStatement(
“providers.put($S, T . b u i l d ( T.build( T.build(T.” + routeMeta.getType() + ", $T.class, $S, $S, null, " + routeMeta.getPriority() + ", " + routeMeta.getExtra() + “))”,
tm.toString(), // So stupid, will duplicate only save class name.
routeMetaCn,
routeTypeCn,
className,
routeMeta.getPath(),
routeMeta.getGroup());
}
}
break;
default:
break;
}

// Make map body for paramsType
… 省略一部分代码…
}

// Generate groups
// ARouter G r o u p Group GroupgroupName
// 见图ARouter G r o u p Group GroupgroupName
String groupFileName = NAME_OF_GROUP + groupName;
JavaFile.builder(PACKAGE_OF_GENERATE_FILE, // com.alibaba.android.arouter.routes
TypeSpec.classBuilder(groupFileName)
.addJavadoc(WARNING_TIPS)
.addSuperinterface(ClassName.get(type_IRouteGroup))
.addModifiers(PUBLIC)
.addMethod(loadIntoMethodOfGroupBuilder.build())
.build()
).build().writeTo(mFiler);

// 组名和用组名生成的类缓存起来
rootMap.put(groupName, groupFileName);

}

if (MapUtils.isNotEmpty(rootMap)) {
// Generate root meta by group name, it must be generated before root, then I can find out the class of group.
for (Map.Entry<String, String> entry : rootMap.entrySet()) {
// 会生成类似这样的代码
// routes.put(“test”, ARouter G r o u p Group Grouptest.class);
// routes.put(“yourservicegroupname”, ARouter G r o u p Group Groupyourservicegroupname.class);
loadIntoMethodOfRootBuilder.addStatement(“routes.put($S, $T.class)”, entry.getKey(), ClassName.get(PACKAGE_OF_GENERATE_FILE, entry.getValue()));
}
}

// Output route doc
… 省略一部分代码…

// Write provider into disk
// ARouter P r o v i d e r s Providers ProvidersmoduleName
// 见图ARouter P r o v i d e r s Providers ProvidersmoduleName
String providerMapFileName = NAME_OF_PROVIDER + SEPARATOR + moduleName;
JavaFile.builder(PACKAGE_OF_GENERATE_FILE, // com.alibaba.android.arouter.routes
TypeSpec.classBuilder(providerMapFileName)
.addJavadoc(WARNING_TIPS)
.addSuperinterface(ClassName.get(type_IProviderGroup))
.addModifiers(PUBLIC)
.addMethod(loadIntoMethodOfProviderBuilder.build())
.build()
).build().writeTo(mFiler);

// ARouter R o o t Root RootmoduleName
// 见图 ARouter R o o t Root RootmoduleName
String rootFileName = NAME_OF_ROOT + SEPARATOR + moduleName;
JavaFile.builder(PACKAGE_OF_GENERATE_FILE,
TypeSpec.classBuilder(rootFileName)
.addJavadoc(WARNING_TIPS)
.addSuperinterface(ClassName.get(elementUtils.getTypeElement(ITROUTE_ROOT)))
.addModifiers(PUBLIC)
.addMethod(loadIntoMethodOfRootBuilder.build())
.build()
).build().writeTo(mFiler);
}

最后

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助

因此我收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点!不论你是刚入门Android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门

如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
715501260876)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点!不论你是刚入门Android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门

如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值