工作流程
应用注解
编译时 arouter_compiler
-
ARouterProcessor
扫描注解 -
封装 RouterBean
-
根据应用类的类型确定TypeMirror
-
生成对应 Path、Group 的 Class,例如 ARouter$$Group$$order,ARouter$$Path$$order
-
ARouter$$Group$$order 保存 group 对应的 path
public Map<String, Class<? extends ARouterPath>> getGroupMap() { Map<String, Class<? extends ARouterPath>> groupMap = new HashMap<>(); groupMap.put("order", ARouter$$Path$$order.class); return groupMap; }
-
ARouter$$Path$$order 保存该组全部 path 对应的 class 关系
public Map<String, RouterBean> getPathMap() { Map<String, RouterBean> pathMap = new HashMap<>(); pathMap.put("/order/getOrderBean", RouterBean.create(RouterBean.TypeEnum.CALL, OrderAddressImpl.class, "/order/getOrderBean", "order")); pathMap.put("/order/getDrawable", RouterBean.create(RouterBean.TypeEnum.CALL, OrderDrawableImpl.class, "/order/getDrawable", "order")); pathMap.put("/order/getUserInfo", RouterBean.create(RouterBean.TypeEnum.CALL, OrderUserImpl.class, "/order/getUserInfo", "order")); pathMap.put("/order/Order_MainActivity", RouterBean.create(RouterBean.TypeEnum.ACTIVITY, Order_MainActivity.class, "/order/Order_MainActivity", "order")); return pathMap; }
使用 RouterManager 跳转
- 根据传入路径拆分 group、记录 group和path
- 寻找 ARouterGroup(ARouter$$Group$$order)、缓存
- 根据 ARouterGroup 寻找 ARouterPath(ARouter$$Path$$order)
- 在 ARouterPath 根据 path 寻找 RouterBean
- 根据 RouterBean 的信息去跳转或者返回调用接口
参数如何传递,赋值(getParameter)
arouter_annotation 模块定义 Parameter 注解
@Target(ElementType.FIELD) // 该注解作用在类之上 字段上有作用
@Retention(RetentionPolicy.CLASS) // 要在编译时进行一些预处理操作,注解会在class文件中存在
public @interface Parameter {
// 不填写name的注解值表示该属性名就是key,填写了就用注解值作为key
// 从getIntent()方法中获取传递参数值
String name() default "";
}
Activity 的字段应用 Parameter
编译时 arouter_compiler
-
ParameterProcessor扫描注解
-
利用工厂
ParameterFactory
构建生成类的内容,该类主要就是一个方法getParameter
-
在bundle里取出对应值赋到字段上即可
// 取到 activity,包含强化转 public void addFirstStatement() { method.addStatement("$T t = ($T) " + ProcessorConfig.PARAMETER_NAME, className, className); } // 取值赋值,因为有多种类型,需细心分多类型判断 /** 多行 循环 复杂 * 构建方体内容,如:t.s = t.getIntent.getStringExtra("s"); * @param element 被注解的属性元素 */ public void buildStatement(Element element) { // 遍历注解的属性节点 生成函数体 TypeMirror typeMirror = element.asType(); // 获取 TypeKind 枚举类型的序列号 int type = typeMirror.getKind().ordinal(); // 获取属性名 name age sex String fieldName = element.getSimpleName().toString(); // 获取注解的值 String annotationValue = element.getAnnotation(Parameter.class).name(); // 配合: t.age = t.getIntent().getBooleanExtra("age", t.age == 9); // 判断注解的值为空的情况下的处理(注解中有name值就用注解值) annotationValue = ProcessorUtils.isEmpty(annotationValue) ? fieldName : annotationValue; // TODO 最终拼接的前缀: String finalValue = "t." + fieldName; // t.s = t.getIntent(). // TODO t.name = t.getIntent().getStringExtra("name"); String methodContent = finalValue + " = t.getIntent()."; // TypeKind 枚举类型不包含String if (type == TypeKind.INT.ordinal()) { // t.s = t.getIntent().getIntExtra("age", t.age); methodContent += "getIntExtra($S, " + finalValue + ")"; // 有默认值 } else if (type == TypeKind.BOOLEAN.ordinal()) { // t.s = t.getIntent().getBooleanExtra("isSuccess", t.age); methodContent += "getBooleanExtra($S, " + finalValue + ")"; // 有默认值 } else { // String 类型,没有序列号的提供 需要我们自己完成 // t.s = t.getIntent.getStringExtra("s"); // typeMirror.toString() java.lang.String if (typeMirror.toString().equalsIgnoreCase(ProcessorConfig.STRING)) { // String类型 methodContent += "getStringExtra($S)"; // 没有默认值 } else if (typeUtils.isSubtype(typeMirror, callMirror)) { // 你居然实现了Call接口 // t.orderDrawable = (OrderDrawable) RouterManager.getInstance().build("/order/getDrawable").navigation(t); methodContent = "t." + fieldName + " = ($T) $T.getInstance().build($S).navigation(t)"; method.addStatement(methodContent, TypeName.get(typeMirror), ClassName.get(ProcessorConfig.AROUTER_API_PACKAGE, ProcessorConfig.ROUTER_MANAGER), annotationValue); return; } else { // 对象的传输 methodContent = "t.getIntent().getSerializableExtra($S)"; } } // 健壮代码 if (methodContent.contains("Serializable")) { // t.student=(Student) t.getIntent().getSerializableExtra("student"); 同学们注意:为了强转 method.addStatement(finalValue + "=($T)" + methodContent, ClassName.get(element.asType()) ,annotationValue); } else if (methodContent.endsWith(")")) { // 抱歉 全部的 getBooleanExtra getIntExtra getStringExtra // 参数二 9 赋值进去了 // t.age = t.getIntent().getBooleanExtra("age", t.age == 9); method.addStatement(methodContent, annotationValue); } else { messager.printMessage(Diagnostic.Kind.ERROR, "目前暂支持String、int、boolean传参"); } }
-
生成 ParameterGet 子类
JavaFile.builder(className.packageName(), // 包名 TypeSpec.classBuilder(finalClassName) // 类名 .addSuperinterface(ClassName.get(parameterType)) // implements ParameterGet 实现ParameterLoad接口 .addModifiers(Modifier.PUBLIC) // public修饰符 .addMethod(factory.build()) // 方法的构建(方法参数 + 方法体) .build()) // 类构建完成 .build() // JavaFile构建完成 .writeTo(filer); // 文件生成器开始生成类文件
在导航时把参数封装到 bundle 里面,用 ParameterManager 管理
Activity 在 onCreate 时调用
ParameterManager.getInstance().loadParameter(this);
调用生成的ParameterGet (Order_MainActivity$$Parameter)类 getParameter 方法赋值
调用其它模块的功能(Call 网络请求、资源res)
基础模块定义功能的 Call 接口
B 模块实现具体逻辑,A 模块要调用其方法
A 模块定义了接口字段
@Parameter(name = "/order/getDrawable")
OrderDrawable orderDrawable; // 公共基础库common
// 拿order模块的 网络请求功能
@Parameter(name = "/order/getOrderBean")
OrderAddress orderAddress;
ParameterProcessor 根据注解自动生成的绑定逻辑:
通过 path 和 RouterManager.navigation(t)
找到具体类并实例化,如
t.orderDrawable = (OrderDrawable) RouterManager.getInstance().build("/order/getDrawable").navigation(t);
t.orderAddress = (OrderAddress) RouterManager.getInstance().build("/order/getOrderBean").navigation(t);
在 Activity 里面调用 ParameterManager.getInstance().loadParameter(this);
自动找到功能的实现类,并实例化对象
直接调用其方法就可使用到其它模块的能力