组件化

组件化一

简介

单一分层问题: 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 字符串,如: SS, ”hello ”

T 类 、 接 口 , 如 : T 类、接口,如: TT, 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);
  }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值