组件化一
简介
单一分层问题: 1.随着项目增大,项目失去层次感,维护困难; 2.包名约束太弱,容易出现不同业务包直接互相调用,代码高耦合; 3.多人开发在版 本管理中,容易出现代码覆盖
(低内聚,高耦合,无重用,层次混乱)
**组件化的意义:**不相互依赖,可以相互交互,任意组合,高度解耦,自由拆卸,自由组装,重复利用, 分层独立化
具体实现: 业务模块(order,login)互相独立不会互相依赖,统一依赖底层模块(base,common,net…),壳模块(app)依赖各个业务模块;
gradle简单使用
抽取各个模块公共变量:1.可以在项目级别的gradle文件中进行定义。2,在项目级别再次定义一个gradle文件,在项目的gradle文件中通过apply from:‘my.gradle’
//my.gradle
ext{
isRelease = false
url = [ "debug" : "https://192.188.22.99/debug",
"release": "https://192.188.22.99/release" ]
androidID=[key:"value"]
appID=[key:"value"]
dependenciesID=[key:"value"]
}
//项目级别gradle
apply from:'my.gradle'//引入my.gradle
//app.gradle
def androidID=rootProject.ext.androidID//定义这个变量出于性能的考虑,可以不定义
//定义变量,可以在代码中通过BuildConfig.isRelease使用
buildConfigField("boolean", "isRelease", String.valueOf(isRelease))
//login.gradle
if (isRelease) { // 如果是发布版本时,各个模块都不能独立运行
apply plugin: 'com.android.library' // 正式环境 library不能独立运行
} else {
apply plugin: 'com.android.application' // 测试环境 application独立运行
}
if (!isRelease) { // 能够独立运行 必须要有appID
applicationId appID.login // 组件化模式能独立运行才能有applicationId
}
sourceSets {
main {
if (!isRelease) {
// manifest.srcFile
manifest.srcFile 'src/main/debug/AndroidManifest.xml' // 生效
} else {
manifest.srcFile 'src/main/AndroidManifest.xml'
java {
// release 时 debug 目录下文件不需要合并到主工程
exclude "**/debug/**"
}
}
}
}
gradle文件大体结构
android {
defaultConfig {}
buildTypes { release {} debug {}}
sourceSets { main { } }
}
dependencies {}
组件化 子模块交互方式
一 使用 EventBus的方式,缺点是:EventBean维护成本太高,不好去管理:
二 使用广播的方式,缺点是:不好管理,都统一发出去了
三 使用隐士意图方式,缺点是:在AndroidManifest.xml里面配置xml写的太多了
四 使用类加载方式,缺点就是,容易写错包名类名,缺点较少(我们尝试写写这种方式)
五 使用全局Map的方式,缺点是,要注册很多的对象(我们尝试写写这种方式)
//app-Application.java
// 如果项目有100个Activity,这种加法会不会太那个? 缺点
RecordPathManager.addGroupInfo("app", "MainActivity", MainActivity.class);
RecordPathManager.addGroupInfo("order", "Order_MainActivity", Order_MainActivity.class);
//order-OrderActivity.java
public void jumpPersonal(View view) {
// todo 方式四 类加载
// 类加载跳转,可以成功。维护成本较高且容易出现人为失误
try {
Class targetClass = Class.forName("com.xiangxue.personal.Personal_MainActivity");
Intent intent = new Intent(this, targetClass);
intent.putExtra("name", "derry");
startActivity(intent);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
// personal/Personal_MainActivity getMap
// todo 方式五 全局Map
Class<?> targetActivity =
RecordPathManager.startTargetActivity("personal", "Personal_MainActivity");
startActivity(new Intent(this, targetActivity));
}
//common-PathBean.java
public class PathBean {
private String path; // personal/Personal_MainActivity
private Class clazz; // Personal_MainActivity.class
...
}
//common-RecordPathManager.java
public class RecordPathManager {
/*
* group: app,order,personal
* order:OrderMainActivity1
*/
private static Map<String, List<PathBean>> maps = new HashMap<>();
/**
* 将路径信息加入全局Map
*
* @param groupName 组名,如:"personal"
* @param pathName 路劲名,如:"Personal_MainActivity"
* @param clazz 类对象,如:Personal_MainActivity.class
*/
public static void addGroupInfo(String groupName, String pathName, Class<?> clazz) {
...
maps.put(groupName, list);
...
}
/**
* 只需要告诉我,组名 ,路径名, 就能返回 "要跳转的Class"
* @param groupName 组名 oder
* @param pathName 路径名 OrderMainActivity1
* @return 跳转目标的class类对象
*/
public static Class<?> startTargetActivity(String groupName, String pathName) {
...
// 遍历 寻找 去匹配 “PathBean”对象
for (PathBean pathBean : list) {
if (pathName.equalsIgnoreCase(pathBean.getPath())) {
return pathBean.getClazz();
}
}
...
}
}
组件化二
APT
APT(Annotation Processing Tool) 处理注释的工具,它对源代码文件进行检测找出其中的Annotation ,根据注解自动生成代码。 如果想要自定义的注解处理器能够正常运行,必须要通过APT工具来进行处理。
通俗理解:根据规则,帮我们生成代码、生成类文
相关类
PackageElement: 包程序元素。提供对有关包及其成员的信息的访问
TypeElement: 类或接口程序元素。提供对有关类型及其成员的信息的访问。
VariableElement: 字段、enum 常量、方法或构造方法参数、局部变量或异常参数
ExecutableElement: 某个类或接口的方法、构造方法或初始化程序(静态或实例)
APT中用到API
getEnclosedElements() 返回该元素直接包含的子元素
getEnclosingElement() 返回包含该element的父element,与上一个方法相反
getKind() 返回element的类型,判断是哪种element
getModifiers() 获取修饰关键字,如public static final等关键字
getSimpleName() 获取名字,不带包名
getQualifiedName() 获取全名,如果是类的话,包含完整的包名路径
getParameters() 获取方法的参数元素,每个元素是一个VariableElement
getReturnType() 获取方法元素的返回值
getConstantValue() 如果属性变量被final修饰,则可以使用该方法获取它的 值
JavaPoet
JavaPoet是square推出开源的java代码生成框架,提供Java Api生成.java源文件;是我们习惯的Java面向对象OOP语法 。
传统方式生成Java文件:一行一行的写入;导包都要自己写
如果复杂的代码生成,反而效率低下
相关类
类对象 | 说明 |
---|---|
MethodSpec | 代表构造函数,或者方法声明 |
TypeSpec | 代表类,接口,枚举声明 |
FieldSpec | 代表成员变量,字段声明 |
JavaFile | 代表顶级类的java文件 |
ParameterSpec | 用来创建参数 |
AnnotationSpec | 用来创建注解 |
ClassName | 用来包装一个类 |
TypeName | 类型,如添加返回值类型是使用 TypeName.VOID |
S 字 符 串 , 如 : S 字符串,如: S字符串,如:S, ”hello ”
T 类 、 接 口 , 如 : T 类、接口,如: T类、接口,如:T, MainActivity
$N:成员变量
$L:枚举
实战项目
@ARouter(path = "/app/MainActivity")
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void startMainActivity3(View view) {
Class startClass = MainActivity3$$$$$$$$$ARouter.findTargetClass("/app/MainActivity3");
}
}
// 通过auto-service中的@AutoService可以自动生成AutoService注解处理器,用来注册
// 用来生成 META-INF/services/javax.annotation.processing.Processor 文件
@AutoService(Processor.class)
@SupportedAnnotationTypes({"com.derry.arouter_annotations.ARouter"}) // 注解
@SupportedSourceVersion(SourceVersion.RELEASE_7) // 环境的版本
// 接收 安卓工程传递过来的参数
@SupportedOptions("student")
public class ARouterProcessor extends AbstractProcessor {
// 操作Element的工具类(类,函数,属性,其实都是Element)
private Elements elementTool;
// type(类信息)的工具类,包含用于操作TypeMirror的工具方法
private Types typeTool;
// Message用来打印 日志相关信息
private Messager messager;
// 文件生成器, 类 资源 等,就是最终要生成的文件 是需要Filer来完成的
private Filer filer;
@Override
public synchronized void init(ProcessingEnvironment processingEnvironment) {
super.init(processingEnvironment);
elementTool = processingEnvironment.getElementUtils();
messager = processingEnvironment.getMessager();
filer = processingEnvironment.getFiler();
String value = processingEnvironment.getOptions().get("student");
}
// 服务:在编译的时候干活
// 坑:如果没有在任何地方使用,次函数是不会工作的
@Override
public boolean process(Set<? extends TypeElement> set, RoundEnvironment roundEnvironment) {
// 这个代码已经下毒了
messager.printMessage(Diagnostic.Kind.NOTE, ">>>>>>> Derry run...");
if (set.isEmpty()) {
return false; // 不干活
}
// 循环?
// 获取被 ARouter注解的 "类节点信息"
Set<? extends Element> elements = roundEnvironment.getElementsAnnotatedWith(ARouter.class);
for (Element element : elements) { // for 3 // 1 element == MainActivity 2 element == MainActivity2
/**
模块一
package com.example.helloworld;
public final class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello, JavaPoet!");
}
}
*/
// Java 万物皆对象
// C 万物皆指针
/*// 1.方法
MethodSpec mainMethod = MethodSpec.methodBuilder("main")
.addModifiers(Modifier.PUBLIC, Modifier.STATIC)
.returns(void.class)
.addParameter(String[].class, "args")
// 增加main方法里面的内容
.addStatement("$T.out.println($S)", System.class, "Hello, JavaPoet!")
.build();
// 2.类
TypeSpec testClass = TypeSpec.classBuilder("DerryTest")
.addMethod(mainMethod)
.addModifiers(Modifier.PUBLIC, Modifier.FINAL)
.build();
// 3.包
JavaFile packagef = JavaFile.builder("com.xiangxue.test", testClass).build();
// 生成文件
try {
packagef.writeTo(filer);
} catch (IOException e) {
e.printStackTrace();
messager.printMessage(Diagnostic.Kind.NOTE, "生成Test文件时失败,异常:" + e.getMessage());
}*/
// 包信息
String packageName = elementTool.getPackageOf(element).getQualifiedName().toString();
// 获取简单类名,例如:MainActivity MainActivity2 MainActivity3
String className = element.getSimpleName().toString();
messager.printMessage(Diagnostic.Kind.NOTE, "被@ARetuer注解的类有:" + className);
// String className = element.getSimpleName().toString();
// 目标:要生成的文件名称 MainActivity$$$$$$$$$ARouter
String finalClassName = className + "$$$$$$$$$ARouter";
/**
模板:
public class MainActivity3$$$$$$$$$ARouter {
public static Class findTargetClass(String path) {
return path.equals("/app/MainActivity3") ? MainActivity3.class : null;
}
}
*/
ARouter aRouter = element.getAnnotation(ARouter.class);
// 1.方法
MethodSpec findTargetClass = MethodSpec.methodBuilder("findTargetClass")
.addModifiers(Modifier.PUBLIC, Modifier.STATIC)
.returns(Class.class)
.addParameter(String.class, "path")
// 方法里面的内容 return path.equals("/app/MainActivity3") ? MainActivity3.class : null;
// 需要JavaPoet包装转型
.addStatement("return path.equals($S) ? $T.class : null",
aRouter.path(),
ClassName.get((TypeElement) element))
.build();
// 2.类
TypeSpec myClass = TypeSpec.classBuilder(finalClassName)
.addMethod(findTargetClass)
.addModifiers(Modifier.PUBLIC)
.build();
// 3.包
JavaFile packagef = JavaFile.builder(packageName, myClass).build();
// 开始生成
try {
packagef.writeTo(filer);
} catch (IOException e) {
e.printStackTrace();
messager.printMessage(Diagnostic.Kind.NOTE, "生成" + finalClassName + "文件时失败,异常:" + e.getMessage());
}
}
// false执行一次 true执行一次,检测一次(内部机制)
return true;
}
}
Arouter
项目结构
app common order personal
arouter_annotation:
arouter_api:
arouter_compiler:
// app.gradle
android {
// compileOptions.encoding = "GBK"
defaultConfig {
buildConfigField("boolean", "isRelease", String.valueOf(isRelease))
// 在gradle文件中配置选项参数值(用于APT传参接收)必须写在defaultConfig节点下 都是为了 传递给 注解处理器//解读
javaCompileOptions {
annotationProcessorOptions {
arguments = [moduleName: project.getName(), packageNameForAPT: packageNameForAPT]
}
}
}
}
dependencies {
// 公共基础库
implementation project(":common")
// arouter 专用 注解模块
implementation project(":arouter_annotation")
// arouter 专用 注解处理器
annotationProcessor project(':arouter_compiler')
if (isRelease) {
implementation project(":order")
implementation project(":personal")
}
}
//person.gradle
android {
defaultConfig {
buildConfigField("boolean", "isRelease", String.valueOf(isRelease))
javaCompileOptions {
annotationProcessorOptions {
arguments = [moduleName: project.getName(), packageNameForAPT: packageNameForAPT]
}
}
}
}
dependencies {
implementation project(":common")
implementation project(":arouter_annotation")
annotationProcessor project(':arouter_compiler')
}
//order.gradle
android {
buildConfigField("boolean", "isRelease", String.valueOf(isRelease))
javaCompileOptions {
annotationProcessorOptions {
// this.project.getName() == order
// this.getProject().getName() == order
arguments = [moduleName: project.getName(), packageNameForAPT: packageNameForAPT]
}
}
}
}
dependencies {
implementation project(":common")
implementation project(":arouter_annotation")
annotationProcessor project(':arouter_compiler')
}
//common.gradle
android {
}
dependencies {
// 因为每一个 “子Module”都依赖了 common,所有当我们在 common中依赖 arouter_api(柱状)
// 就等于 全部都依赖了 arouter_api
api project(":arouter_api")
}
//arouter_compiler.gradle
apply plugin: 'java-library'
dependencies {
// AS 4.3.1 -> 4.0.1 没有问题
// As-3.4.1 + gradle-5.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'
// 帮助我们通过类调用的形式来生成Java代码
implementation "com.squareup:javapoet:1.9.0"
// 引入annotation,处理@ARouter注解
implementation project(':arouter_annotation')
}
// java控制台输出中文乱码
tasks.withType(JavaCompile) {
options.encoding = "UTF-8"
}
sourceCompatibility = "7"
targetCompatibility = "7"
//arouter_api.gradle
android {
}
dependencies {
// 引入注解中RouterBean对象(java项目才有javax.lang包)
implementation project(':arouter_annotation')
}
//arouter_annotation.gradle
apply plugin: 'java-library'
// java控制台输出中文乱码
tasks.withType(JavaCompile) {
options.encoding = "UTF-8"
}
sourceCompatibility = "7"
targetCompatibility = "7"
组件化三
跳转activity
//具体实现类会new一个hashMaep,将所有的RouterBean添加进去后,返回;
public interface ARouterPath {
//key:"/order/Order_MainActivity"
//value: Order_MainActivity.class RouterBean
Map<String, RouterBean> getPathMap();
}
public interface ARouterGroup {
//key:"order/app/personal"
//value:系列的order组下面所有的(path---class)
Map<String, Class<? extends ARouterPath>> getGroupMap();
}
//APT中判断是否Activity的子类
// 通过Element工具类,获取Activity,Callback类型
TypeElement activityType = elementTool.getTypeElement(ProcessorConfig.ACTIVITY_PACKAGE);
// 显示类信息(获取被注解的节点,类节点)这也叫自描述 Mirror android.app.Activity描述信息
TypeMirror activityMirror = activityType.asType();
TypeMirror elementMirror = element.asType(); // Main2Activity的具体详情
// typeTool.isSubtype方法判断
if (typeTool.isSubtype(elementMirror, activityMirror)) {
routerBean.setTypeEnum(RouterBean.TypeEnum.ACTIVITY);
} else {
// 不匹配抛出异常,这里谨慎使用!考虑维护问题
throw new RuntimeException("@ARouter注解目前仅限用于Activity类之上");
}
//APT生成带泛型的class
// Map<String, RouterBean>
TypeName methodReturn = ParameterizedTypeName.get(
ClassName.get(Map.class), // Map
ClassName.get(String.class), // Map<String,
ClassName.get(RouterBean.class) // Map<String, RouterBean>
);
// Class<? extends ARouterPath>> 难度
ParameterizedTypeName.get(ClassName.get(Class.class),
// ? extends ARouterPath
WildcardTypeName.subtypeOf(ClassName.get(pathType)))
//继承和重写方法
TypeSpec.classBuilder(finalClassName) // 类名
.addSuperinterface(ClassName.get(pathType)) // 实现ARouterLoadPath接口 implements ARouterPath==pathType
MethodSpec.methodBuilder(ProcessorConfig.PATH_METHOD_NAME)
.addAnnotation(Override.class) // 给方法上添加注解 @Override
使用
//app
//MainActivity.java
public void jumpPersonal(View view) {
// 以前是这样跳转
/*Intent intent = new Intent(this, Personal_MainActivity.class);
intent.putExtra("name", "derry");
startActivity(intent);*/
// 现在是这样跳转 目前还要写这么多代码,是不是非常累
// TODO 最终的成效:用户 一行代码搞定,同时还可以传递参数,同时还可以懒加载
ARouter$$Group$$personal group$$personal = new ARouter$$Group$$personal();
Map<String, Class<? extends ARouterPath>> groupMap = group$$personal.getGroupMap();
Class<? extends ARouterPath> myClass = groupMap.get("personal");
try {
ARouter$$Path$$personal path = (ARouter$$Path$$personal) myClass.newInstance();
Map<String, RouterBean> pathMap = path.getPathMap();
RouterBean bean = pathMap.get("/personal/Personal_MainActivity");
if (bean != null) {
Intent intent = new Intent(this, bean.getMyClass());
startActivity(intent);
}
} catch (Exception e) {
e.printStackTrace();
}
}
组件化四
跳转传递参数,通过懒加载的方法,在目标Activity的成员上加上对应的注解;通过intent传递;
1.arouter_annotation 添加注解 Parameter
2.arouter_api ParaneterGet标准规则的定义
3.arouter_compiler ParameterProcessor注解处理器生成刚刚分析的模板代码
4.arouter_api ParamaterManager参数管理器的编写
ARouterProcessor.java :生成文件,使得这个文件的方法产生一个map,这个map返回之前存储了所有被@ARoute注解的类的calss。key是ARoute注解中传入的pathj。
RouterManager:构造时会传入path。通过截取path拼接文件名,查找ParameterProcessor生成的文件,调用方法获取已经存了class的map。再通过map,通过key:path查找到对应的class。可以完成跳转,通过with方法传值,通过intent传输。
ParameterProcessor.java:生成文件,使得这个文件的方法可以对传入的参数中的对象中的成员赋值。这些被赋值的成员都是被@Parameter注解的。赋的值是通过取出intent中的数据。字段的名字,要与intent传值是的key对应。
ParameterManager:调用方法时会传入要赋值成员的对象,通过对象类名拼接后直接得到ARouterProcessor生成文件的名字,可以创建对象,调用对应的方法,赋值。
public interface ParameterGet {
/**
* 目标对象.属性名 = getIntent().属性类型... 完成赋值操作
* @param targetParameter 目标对象:例如:MainActivity 中的那些属性
*/
void getParameter(Object targetParameter);
}
//arouter_compiler
//ParameterProcessor.java
// 临时map,存放被@Parameter注解的属性集合,生成类文件时遍历
// key:类节点, value:被@Parameter注解的属性集合
private Map<TypeElement, List<Element>> tempParameterMap = new HashMap<>();
// 注解在属性的上面,属性节点父节点 是 类节点
TypeElement enclosingElement = (TypeElement) element.getEnclosingElement();
//implements ParameterGet 实现ParameterLoad接口
TypeSpec.classBuilder(finalClassName) .addSuperinterface(ClassName.get(parameterType))
//ParameterFactory.java
// 通过方法参数体构建方法体:就是重写public void getParameter(Object target) {}
method = MethodSpec.methodBuilder(ProcessorConfig.PARAMETER_METHOD_NAME)
.addAnnotation(Override.class);
public void buildStatement(Element element) {
// 遍历注解的属性节点 生成函数体
TypeMirror typeMirror = element.asType();
// 获取 TypeKind 枚举类型的序列号
int type = typeMirror.getKind().ordinal();
...
if (type == TypeKind.INT.ordinal()) {
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)"; // 没有默认值
}
}
...
}
//arouter_api
//ParameterManager.java
// 使用者 只需要调用这一个方法,就可以进行参数的接收
public void loadParameter(Activity activity) { // 必须拿到 Personal_MainActivity
String className = activity.getClass().getName();
ParameterGet parameterLoad = cache.get(className);
if (null == parameterLoad) { // 缓存里面没东东 提高性能
// 拼接 如:Order_MainActivity + $$Parameter
try {
// 类加载Personal_MainActivity + $$Parameter
Class<?> aClass = Class.forName(className + FILE_SUFFIX_NAME);
// 用接口parameterLoad = 接口的实现类Personal_MainActivity
parameterLoad = (ParameterGet) aClass.newInstance(); cache.put(className, parameterLoad); // 保存到缓存
} catch (Exception e) {
e.printStackTrace();
}
}
parameterLoad.getParameter(activity); // 最终的执行 会执行我们生成的类
}
//RouterManager.java
// 真正的导航
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
public Object navigation(Context context, BundleManager bundleManager) {
// 例如:寻找 ARouter$$Group$$personal 寻址 ARouter$$Group$$order ARouter$$Group$$app
String groupClassName = context.getPackageName() + "." + FILE_GROUP_NAME + group;
try {
// TODO 第一步 读取路由组Group类文件
...
// TODO 第二步 读取路由Path类文件
...
// TODO 第三步 跳转
if (loadPath != null) { // 健壮
// 最后才执行操作
RouterBean routerBean = loadPath.getPathMap().get(path);
if (routerBean != null) {
switch (routerBean.getTypeEnum()) {
case ACTIVITY:
Intent intent = new Intent(context, routerBean.getMyClass());
intent.putExtras(bundleManager.getBundle()); // 携带参数
context.startActivity(intent, bundleManager.getBundle());
break;
//同学们可以自己扩展 类型
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
使用
//app
//MainActivity.java
public void jumpPersonal(View view) {
// 使用我们自己写的路由 跳转交互
RouterManager.getInstance()
.build("/personal/Personal_MainActivity")
.withString("name", "史甄湘")
.withString("sex", "男")
.withInt("age", 99)
.navigation(this);
}
//person
//MainActivity.java
@Parameter
String name; // 序列号 String
@Parameter
String sex;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.personal_activity_main);
// 模仿人家了 bind(this);
ParameterManager.getInstance().loadParameter(this);
}
组件化五
传递图片,传递Bean,调用方法的使用方法都是用懒加载的方法进行的;在目标Activity的成员上加上@parameter注解;而要传递的数据定义成Call,用@Arouter 注解;
1.arouter_api Call 标准规则的定义
2.common OrderDrawable 继承Call order组图片标准规则的定义
3.order OrderDrawableImpl 最终的具体实现交给具体模块order
4.arouter_compiler ARouterProcessor 修改代码
5.app MainActivity 使用图片到ImageView 有问题 进入第六步
6.arouter_compiler ParameterProcessor / ParameterFactory 修改代码
7.arouter_api RouterManager / BundleManager 修改代码
ARouterProcessor.java :生成文件,使得这个文件的方法产生一个map,这个map返回之前存储了所有被@ARoute注解的类的calss。key是ARoute注解中传入的path。
RouterManager:构造时会传入path。通过截取path拼接文件名,查找ParameterProcessor生成的文件,调用方法获取已经存了class的map。再通过map,通过key:path查找到对应的class。可以完成跳转,通过with方法传值,通过intent传输。如果class是Call,那么会实例化对象,并返回
ParameterProcessor.java:生成文件,使得这个文件的方法可以对传入的参数中的对象中的成员赋值。这些被赋值的成员都是被@Parameter注解的。赋的值是通过取出intent中的数据。字段的名字,要与intent传值是的key对应。如果是Call类型,那么值不是从intent中获取,而是调用RouterManager的navigation方法获取;这个时候取出Parameter注解中的值当时做path传入RouterManager。
ParameterManager:调用方法时会传入要赋值成员的对象,通过对象类名拼接后直接得到ARouterProcessor生成文件的名字,可以创建对象,调用对应的方法,赋值。
//arouter_api-Call.java
public interface Call {
}
//common-OrderDrawable.java
public interface OrderDrawable extends Call {
int getDrawable();
}
//order-OrderDrawableImpl.java
// order 自己决定 自己的暴漏;
//使用@ARouter,现在@ARouter被用在继承Activity和Call两个地方
@ARouter(path = "/order/getDrawable")
public class OrderDrawableImpl implements OrderDrawable {
@Override
public int getDrawable() {
return R.drawable.ic_ac_unit_black_24dp;
}
}
//arouter_compiler-ARouterProcessor.java
// TODO 新增点1
TypeElement callType = elementTool.getTypeElement(ProcessorConfig.CALL);
TypeMirror callMirror = callType.asType(); // 自描述 callMirror
if (typeTool.isSubtype(elementMirror, activityMirror)) {
routerBean.setTypeEnum(RouterBean.TypeEnum.ACTIVITY);
} else if (typeTool.isSubtype(elementMirror, callMirror)) { // TODO 新增点2
routerBean.setTypeEnum(RouterBean.TypeEnum.CALL);
}
//arouter_compiler
//ParameterProcessor.java
// 将elementUtils传入ParameterFactory
ParameterFactory factory = new ParameterFactory.Builder(parameterSpec)
.setMessager(messager)
.setElementUtils(elementUtils) // TODO 新增点
.setTypeUtils(typeUtils)
.setClassName(className)
.build();
//ParameterFactory.java
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)";
}
//arouter_api
//RouterManager.java
public Object navigation(Context context, BundleManager bundleManager) {
...
switch (routerBean.getTypeEnum()) {
case ACTIVITY:
Intent intent = new Intent(context, routerBean.getMyClass());
intent.putExtras(bundleManager.getBundle());
context.startActivity(intent);
break;
case CALL:
// OrderAddressImpl.class OrderBean getOrderBean
// OrderUserImpl BaseUser实体
Class<?> clazz = routerBean.getMyClass();
Call call = (Call) clazz.newInstance();
bundleManager.setCall(call);
return bundleManager.getCall();
//同学们可以自己扩展 类型
}
...
}
使用
//使用@ARouter,现在@ARouter被用在继承Activity和Call两个地方
@ARouter(path = "/order/getDrawable")
public class OrderDrawableImpl implements OrderDrawable {
@Override
public int getDrawable() {
return R.drawable.ic_ac_unit_black_24dp;
}
}
//app-MainActivity
@Parameter(name = "/order/getDrawable")
OrderDrawable orderDrawable; // 公共基础库common
// 拿order模块的 网络请求功能
@Parameter(name = "/order/getOrderBean")
OrderAddress orderAddress;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 懒加载方式,跳到哪加载哪个类
ParameterManager.getInstance().loadParameter(this);
// app模块本来就可以直接加载其他模块的资源 personal
// 拿到 order模块的图片 在app模块展示
int drawableId = orderDrawable.getDrawable();
ImageView img = findViewById(R.id.img);
img.setImageResource(drawableId);
}
补充
//order模块生成的类
public class ARouter$$Group$$order implements ARouterGroup {
@Override
public Map<String, Class<? extends ARouterPath>> getGroupMap() {
Map<String, Class<? extends ARouterPath>> groupMap = new HashMap<>();
groupMap.put("order", ARouter$$Path$$order.class);
return groupMap;
}
}
public class ARouter$$Path$$order implements ARouterPath {
@Override
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;
}
}
public class Order_MainActivity$$Parameter implements ParameterGet {
@Override
public void getParameter(Object targetParameter) {
Order_MainActivity t = (Order_MainActivity) targetParameter;
t.name = t.getIntent().getStringExtra("name");
}
}
//Personal模块生成的类
public class Personal_MainActivity$$Parameter implements ParameterGet {
@Override
public void getParameter(Object targetParameter) {
Personal_MainActivity t = (Personal_MainActivity) targetParameter;
t.name = t.getIntent().getStringExtra("name");
t.sex = t.getIntent().getStringExtra("sex");
t.age = t.getIntent().getIntExtra("age", t.age);
t.student=(Student)t.getIntent().getSerializableExtra("student");
t.orderDrawable = (OrderDrawable) RouterManager.getInstance().build("/order/getDrawable").navigation(t);
t.orderAddress = (OrderAddress) RouterManager.getInstance().build("/order/getOrderBean").navigation(t);
}
}