组件化之路由架构设计与实现(三)

目录

  • 路由架构设计
  • APT生成路由Group和Path类文件
  • APT生成路由动态参数文件

路由架构设计

在这里插入图片描述
问题一 为什么需要组名

分模块加载,利用这种“懒加载”模式,能够最大程度上减少内存的使用

问题二 生成文件有什么作用

生成的文件便于记录管理activity字节码对象

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

组件化项目部署

在这里插入图片描述

1)配置arouter_api/build.gradle

a.定义ARouterLoadGroup、ARouterLoadPath接口

b.在build.gradle声明依赖
    implementation project(":arouter_annotation")

2)配置common/build.gradle

implementation project(":arouter_annotation")
api project(":arouter_api")

3)完成模拟APT生成类的代码

    public class ARouter$$Group$$Order implements ARouterLoadGroup {
    
        @Override
        public HashMap<String, Class<? extends ARouterLoadPath>> loadGroup() {
            HashMap<String, Class<? extends ARouterLoadPath>> map = new HashMap<>();
            //初始化appGroup
            map.put("order", ARouter$$Path$$Order.class);
            return map;
        }
    }
    
    
    public class ARouter$$Path$$Order implements ARouterLoadPath {

        @Override
        public HashMap<String, RouterBean> loadPath() {
            HashMap<String, RouterBean> map = new HashMap<>();
    
            //加入/app/MainActivity
            map.put("/order/OrderMainActivity",
                    RouterBean.create(OrderMainActivity.class,
                            "/order/OrderMainActivity",
                            "order"));
    
            return map;
        }
    }

4)App子模块中,模拟跳转代码

     public void jumpOrder(View v){

        //获取要跳转的ARouterLoadGroup对象
        ARouterLoadGroup group = new ARouter$$Group$$Order();
        HashMap<String, Class<? extends ARouterLoadPath>> groupMap = group.loadGroup();
        
        //获取ARouterLoadPath模块
        Class<? extends ARouterLoadPath> orderClazz = groupMap.get("order");
        try {
            ARouterLoadPath loadPath = orderClazz.newInstance();
            HashMap<String, RouterBean> pathMap = loadPath.loadPath();
            //根据路径获取RouterBean对象
            RouterBean routerBean = pathMap.get("/order/OrderMainActivity");
            if (routerBean != null) {
                startActivity(new Intent(this, routerBean.getClazz()));
            }
        } catch (Exception e) {
            e.printStackTrace();
        } 
    }

5)演示跳转
测试OK

APT生成路由Group和Path类文件

需要生成如下两个文件
在这里插入图片描述

配置模块需要传递的参数

当前注解处理器处理的模块名称
生成代码的包名


// 在gradle文件中配置选项参数值(用于APT传参接收)
// 切记:必须写在defaultConfig节点下
javaCompileOptions {
    annotationProcessorOptions {
        arguments = [moduleName :project.getName(),packageNameForAPT:packageNameForAPT]
    }
}

动态生成group 和path文件

/**
 * 编码此类1句话:细心再细心,出了问题debug真的不好调试
 */
// AutoService则是固定的写法,加个注解即可
// 通过auto-service中的@AutoService可以自动生成AutoService注解处理器,用来注册
// 用来生成 META-INF/services/javax.annotation.processing.Processor 文件
@AutoService(Processor.class)
// 允许/支持的注解类型,让注解处理器处理
@SupportedAnnotationTypes({Constants.AROUTER_ANNOTATION_TYPES})
// 指定JDK编译版本
@SupportedSourceVersion(SourceVersion.RELEASE_7)
// 注解处理器接收的参数
@SupportedOptions({Constants.MODULE_NAME, Constants.APT_PACKAGE})
public class ARouterProcessor extends AbstractProcessor {

    // 操作Element工具类 (类、函数、属性都是Element)
    private Elements elementUtils;

    // type(类信息)工具类,包含用于操作TypeMirror的工具方法
    private Types typeUtils;

    // Messager用来报告错误,警告和其他提示信息
    private Messager messager;

    // 文件生成器 类/资源,Filter用来创建新的类文件,class文件以及辅助文件
    private Filer filer;

    // 子模块名,如:app/order/personal。需要拼接类名时用到(必传)ARouter$$Group$$order
    private String moduleName;

    // 包名,用于存放APT生成的类文件
    private String packageNameForAPT;

    // 临时map存储,用来存放路由组Group对应的详细Path类对象,生成路由路径类文件时遍历
    // key:组名"app", value:"app"组的路由路径"ARouter$$Path$$app.class"
    private Map<String, List<RouterBean>> tempPathMap = new HashMap<>();

    // 临时map存储,用来存放路由Group信息,生成路由组类文件时遍历
    // key:组名"app", value:类名"ARouter$$Path$$app.class"
    private Map<String, String> tempGroupMap = new HashMap<>();

    // 该方法主要用于一些初始化的操作,通过该方法的参数ProcessingEnvironment可以获取一些列有用的工具类
    @Override
    public synchronized void init(ProcessingEnvironment processingEnvironment) {
        super.init(processingEnvironment);
        elementUtils = processingEnvironment.getElementUtils();
        typeUtils = processingEnvironment.getTypeUtils();
        messager = processingEnvironment.getMessager();
        filer = processingEnvironment.getFiler();

        // 通过ProcessingEnvironment去获取对应的参数
        Map<String, String> options = processingEnvironment.getOptions();
        if (!EmptyUtils.isEmpty(options)) {
            moduleName = options.get(Constants.MODULE_NAME);
            packageNameForAPT = options.get(Constants.APT_PACKAGE);
            // 有坑:Diagnostic.Kind.ERROR,异常会自动结束,不像安卓中Log.e
            messager.printMessage(Diagnostic.Kind.NOTE, "moduleName >>> " + moduleName);
            messager.printMessage(Diagnostic.Kind.NOTE, "packageNameForAPT >>> " + packageNameForAPT);
        }

        // 必传参数判空(乱码问题:添加java控制台输出中文乱码)
        if (EmptyUtils.isEmpty(moduleName) || EmptyUtils.isEmpty(packageNameForAPT)) {
            throw new RuntimeException("注解处理器需要的参数moduleName或者packageName为空,请在对应build.gradle配置参数");
        }
    }

    /**
     * 相当于main函数,开始处理注解
     * 注解处理器的核心方法,处理具体的注解,生成Java文件
     *
     * @param set              使用了支持处理注解的节点集合
     * @param roundEnvironment 当前或是之前的运行环境,可以通过该对象查找的注解。
     * @return true 表示后续处理器不会再处理(已经处理完成)
     */
    @Override
    public boolean process(Set<? extends TypeElement> set, RoundEnvironment roundEnvironment) {
        // 一旦有类之上使用@ARouter注解
        if (!EmptyUtils.isEmpty(set)) {
            // 获取所有被 @ARouter 注解的 元素集合
            Set<? extends Element> elements = roundEnvironment.getElementsAnnotatedWith(ARouter.class);

            if (!EmptyUtils.isEmpty(elements)) {
                // 解析元素
                try {
                    parseElements(elements);
                    return true;
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            // 坑:必须写返回值,表示处理@ARouter注解完成
            return true;
        }
        return false;
    }

    // 解析所有被 @ARouter 注解的 类元素集合
    private void parseElements(Set<? extends Element> elements) throws IOException {
        // 通过Element工具类,获取Activity、Callback类型
        TypeElement activityType = elementUtils.getTypeElement(Constants.ACTIVITY);

        // 显示类信息(获取被注解节点,类节点)这里也叫自描述 Mirror
        TypeMirror activityMirror = activityType.asType();

        // 遍历节点
        for (Element element : elements) {
            // 获取每个元素类信息,用于比较
            TypeMirror elementMirror = element.asType();
            messager.printMessage(Diagnostic.Kind.NOTE, "遍历元素信息:" + elementMirror.toString());

            // 获取每个类上的@ARouter注解中的注解值
            ARouter aRouter = element.getAnnotation(ARouter.class);

            // 路由详细信息,最终实体封装类
            RouterBean bean = new RouterBean.Builder()
                    .setGroup(aRouter.group())
                    .setPath(aRouter.path())
                    .setElement(element)
                    .build();

            // 高级判断:ARouter注解仅能用在类之上,并且是规定的Activity
            // 类型工具类方法isSubtype,相当于instance一样
            if (typeUtils.isSubtype(elementMirror, activityMirror)) {
                bean.setType(RouterBean.Type.ACTIVITY);
            } else {
                // 不匹配抛出异常,这里谨慎使用!考虑维护问题
                throw new RuntimeException("@ARouter注解目前仅限用于Activity类之上");
            }

            // 赋值临时map存储,用来存放路由组Group对应的详细Path类对象
            valueOfPathMap(bean);
        }

        // routerMap遍历后,用来生成类文件

        // 获取ARouterLoadGroup、ARouterLoadPath类型(生成类文件需要实现的接口)
        TypeElement groupLoadType = elementUtils.getTypeElement(Constants.AROUTE_GROUP); // 组接口
        TypeElement pathLoadType = elementUtils.getTypeElement(Constants.AROUTE_PATH); // 路径接口

        // 第一步:生成路由组Group对应详细Path类文件,如:ARouter$$Path$$app
        createPathFile(pathLoadType);

        // 第二步:生成路由组Group类文件(没有第一步,取不到类文件),如:ARouter$$Group$$app
        createGroupFile(groupLoadType, pathLoadType);
    }

    /**
     * 生成路由组Group对应详细Path,如:ARouter$$Path$$app
     *
     * @param pathLoadType ARouterLoadPath接口信息
     */
    private void createPathFile(TypeElement pathLoadType) throws IOException {
        // 判断是否有需要生成的类文件
        if (EmptyUtils.isEmpty(tempPathMap)) return;

        TypeName methodReturns = ParameterizedTypeName.get(
                ClassName.get(Map.class), // Map
                ClassName.get(String.class), // Map<String,
                ClassName.get(RouterBean.class) // Map<String, RouterBean>
        );

        // 遍历分组,每一个分组创建一个路径类文件,如:ARouter$$Path$$app
        for (Map.Entry<String, List<RouterBean>> entry : tempPathMap.entrySet()) {
            // 方法配置:public Map<String, RouterBean> loadPath() {
            MethodSpec.Builder methodBuidler = MethodSpec.methodBuilder(Constants.PATH_METHOD_NAME) // 方法名
                    .addAnnotation(Override.class) // 重写注解
                    .addModifiers(Modifier.PUBLIC) // public修饰符
                    .returns(methodReturns); // 方法返回值

            // 遍历之前:Map<String, RouterBean> pathMap = new HashMap<>();
            methodBuidler.addStatement("$T<$T, $T> $N = new $T<>()",
                    ClassName.get(Map.class),
                    ClassName.get(String.class),
                    ClassName.get(RouterBean.class),
                    Constants.PATH_PARAMETER_NAME,
                    HashMap.class);

            // 一个分组,如:ARouter$$Path$$app。有很多详细路径信息,如:/app/MainActivity、/app/OtherActivity
            List<RouterBean> pathList = entry.getValue();
            // 方法内容配置(遍历每个分组中每个路由详细路径)
            for (RouterBean bean : pathList) {
                // 类似String.format("hello %s net163 %d", "net", 163)通配符
                // pathMap.put("/app/MainActivity", RouterBean.create(
                //        RouterBean.Type.ACTIVITY, MainActivity.class, "/app/MainActivity", "app"));
                methodBuidler.addStatement(
                        "$N.put($S, $T.create($T.$L, $T.class, $S, $S))",
                        Constants.PATH_PARAMETER_NAME, // pathMap.put
                        bean.getPath(), // "/app/MainActivity"
                        ClassName.get(RouterBean.class), // RouterBean
                        ClassName.get(RouterBean.Type.class), // RouterBean.Type
                        bean.getType(), // 枚举类型:ACTIVITY
                        ClassName.get((TypeElement) bean.getElement()), // MainActivity.class
                        bean.getPath(), // 路径名
                        bean.getGroup() // 组名
                );
            }

            // 遍历之后:return pathMap;
            methodBuidler.addStatement("return $N", Constants.PATH_PARAMETER_NAME);

            // 最终生成的类文件名
            String finalClassName = Constants.PATH_FILE_NAME + entry.getKey();
            messager.printMessage(Diagnostic.Kind.NOTE, "APT生成路由Path类文件:" +
                    packageNameForAPT + "." + finalClassName);

            // 生成类文件:ARouter$$Path$$app
            JavaFile.builder(packageNameForAPT, // 包名
                    TypeSpec.classBuilder(finalClassName) // 类名
                            .addSuperinterface(ClassName.get(pathLoadType)) // 实现ARouterLoadPath接口
                            .addModifiers(Modifier.PUBLIC) // public修饰符
                            .addMethod(methodBuidler.build()) // 方法的构建(方法参数 + 方法体)
                            .build()) // 类构建完成
                    .build() // JavaFile构建完成
                    .writeTo(filer); // 文件生成器开始生成类文件

            // 非常重要一步!!!!!路径文件生成出来了,才能赋值路由组tempGroupMap
            tempGroupMap.put(entry.getKey(), finalClassName);
        }
    }

    /**
     *
     * public interface ARouterLoadGroup {
     *
     *     HashMap<String,Class<? extends ARouterLoadPath>> loadGroup();
     * }
     * 生成路由组Group文件,如:ARouter$$Group$$app
     *
     * @param groupLoadType ARouterLoadGroup接口信息
     * @param pathLoadType ARouterLoadPath接口信息
     */
    private void createGroupFile(TypeElement groupLoadType, TypeElement pathLoadType) throws IOException {
        // 判断是否有需要生成的类文件
        if (EmptyUtils.isEmpty(tempGroupMap) || EmptyUtils.isEmpty(tempPathMap)) return;

        TypeName methodReturns = ParameterizedTypeName.get(
                ClassName.get(Map.class), // Map
                ClassName.get(String.class), // Map<String,
                // 第二个参数:Class<? extends ARouterLoadPath>
                // 某某Class是否属于ARouterLoadPath接口的实现类
                ParameterizedTypeName.get(ClassName.get(Class.class),
                        WildcardTypeName.subtypeOf(ClassName.get(pathLoadType)))
        );

        // 方法配置:public Map<String, Class<? extends ARouterLoadPath>> loadGroup() {
        MethodSpec.Builder methodBuidler = MethodSpec.methodBuilder(Constants.GROUP_METHOD_NAME) // 方法名
                .addAnnotation(Override.class) // 重写注解
                .addModifiers(Modifier.PUBLIC) // public修饰符
                .returns(methodReturns); // 方法返回值

        // 遍历之前:Map<String, Class<? extends ARouterLoadPath>> groupMap = new HashMap<>();
        methodBuidler.addStatement("$T<$T, $T> $N = new $T<>()",
                ClassName.get(Map.class),
                ClassName.get(String.class),
                ParameterizedTypeName.get(ClassName.get(Class.class),
                        WildcardTypeName.subtypeOf(ClassName.get(pathLoadType))),
                Constants.GROUP_PARAMETER_NAME,
                HashMap.class);

        // 方法内容配置
        for (Map.Entry<String, String> entry : tempGroupMap.entrySet()) {
            // 类似String.format("hello %s net163 %d", "net", 163)通配符
            // groupMap.put("main", ARouter$$Path$$app.class);
            methodBuidler.addStatement("$N.put($S, $T.class)",
                    Constants.GROUP_PARAMETER_NAME, // groupMap.put
                    entry.getKey(),
                    // 类文件在指定包名下
                    ClassName.get(packageNameForAPT, entry.getValue()));
        }

        // 遍历之后:return groupMap;
        methodBuidler.addStatement("return $N", Constants.GROUP_PARAMETER_NAME);

        // 最终生成的类文件名
        String finalClassName = Constants.GROUP_FILE_NAME + moduleName;
        messager.printMessage(Diagnostic.Kind.NOTE, "APT生成路由组Group类文件:" +
                packageNameForAPT + "." + finalClassName);

        // 生成类文件:ARouter$$Group$$app
        JavaFile.builder(packageNameForAPT, // 包名
                TypeSpec.classBuilder(finalClassName) // 类名
                        .addSuperinterface(ClassName.get(groupLoadType)) // 实现ARouterLoadGroup接口
                        .addModifiers(Modifier.PUBLIC) // public修饰符
                        .addMethod(methodBuidler.build()) // 方法的构建(方法参数 + 方法体)
                        .build()) // 类构建完成
                .build() // JavaFile构建完成
                .writeTo(filer); // 文件生成器开始生成类文件
    }

    /**
     * 赋值临时map存储,用来存放路由组Group对应的详细Path类对象,生成路由路径类文件时遍历
     *
     * @param bean 路由详细信息,最终实体封装类
     */
    private void valueOfPathMap(RouterBean bean) {
        if (checkRouterPath(bean)) {
            messager.printMessage(Diagnostic.Kind.NOTE, "RouterBean >>> " + bean.toString());

            // 开始赋值Map
            List<RouterBean> routerBeans = tempPathMap.get(bean.getGroup());
            // 如果从Map中找不到key为:bean.getGroup()的数据,就新建List集合再添加进Map
            if (EmptyUtils.isEmpty(routerBeans)) {
                routerBeans = new ArrayList<>();
                routerBeans.add(bean);
                tempPathMap.put(bean.getGroup(), routerBeans);
            } else { // 找到了key,直接加入List集合
                routerBeans.add(bean);
            }

        } else {
            messager.printMessage(Diagnostic.Kind.ERROR, "@ARouter注解未按规范配置,如:/app/MainActivity");
        }
    }

    /**
     * 校验@ARouter注解的值,如果group未填写就从必填项path中截取数据
     *
     * @param bean 路由详细信息,最终实体封装类
     */
    private boolean checkRouterPath(RouterBean bean) {
        String group = bean.getGroup();
        String path = bean.getPath();

        // @ARouter注解中的path值,必须要以 / 开头(模仿阿里Arouter规范)
        if (EmptyUtils.isEmpty(path) || !path.startsWith("/")) {
            messager.printMessage(Diagnostic.Kind.ERROR, "@ARouter注解中的path值,必须要以 / 开头");
            return false;
        }

        // 比如开发者代码为:path = "/MainActivity",最后一个 / 符号必然在字符串第1位
        if (path.lastIndexOf("/") == 0) {
            // 架构师定义规范,让开发者遵循
            messager.printMessage(Diagnostic.Kind.ERROR, "@ARouter注解未按规范配置,如:/app/MainActivity");
            return false;
        }

        // 从第一个 / 到第二个 / 中间截取,如:/app/MainActivity 截取出 app 作为group
        String finalGroup = path.substring(1, path.indexOf("/", 1));

        // @ARouter注解中的group有赋值情况
        if (!EmptyUtils.isEmpty(group) && !group.equals(moduleName)) {
            // 架构师定义规范,让开发者遵循
            messager.printMessage(Diagnostic.Kind.ERROR, "@ARouter注解中的group值必须和子模块名一致!");
            return false;
        } else {
            bean.setGroup(finalGroup);
        }

        return true;
    }
}

APT生成路由动态参数文件

正常情况下,参数接收如下:

在这里插入图片描述

组件化中,参数接收如下:
在这里插入图片描述

  1. 声明参数注解

     @Target(ElementType.FIELD) // 该注解作用在属性之上
     @Retention(RetentionPolicy.CLASS)
     public @interface Parameter {
     
         // 不填写name的注解值表示该属性名就是key,填写了就用注解值作为key
         // 从getIntent()方法中获取传递参数值
         String name() default "";
     }
    
  2. 模拟要生成的注解方法

     public class MainActivity$$Parameter implements ParameterLoad {
       @Override
       public void loadParameter(Object target) {
         MainActivity t = (MainActivity)target;
         t.name = t.getIntent().getStringExtra("name");
         t.agex = t.getIntent().getStringExtra("agex");
       }
     }
    
  3. 实现注解解析类

     @AutoService(Processor.class)
     @SupportedAnnotationTypes({Constants.PARAMETER_ANNOTATION_TYPES})
     @SupportedSourceVersion(SourceVersion.RELEASE_7)
     public class ParameterProcessor extends AbstractProcessor {
     
         private Elements elementUtils;
         private Types typeUtils;
         private Messager messager;
         private Filer filer;
     
         // 临时map存储,用来存放被@Parameter注解的属性集合,生成类文件时遍历
         // key:类节点, value:被@Parameter注解的属性集合
         private Map<TypeElement, List<Element>> tempParameterMap = new HashMap<>();
     
         @Override
         public synchronized void init(ProcessingEnvironment processingEnvironment) {
             super.init(processingEnvironment);
             elementUtils = processingEnvironment.getElementUtils();
             typeUtils = processingEnvironment.getTypeUtils();
             messager = processingEnvironment.getMessager();
             filer = processingEnvironment.getFiler();
         }
     
         @Override
         public boolean process(Set<? extends TypeElement> set, RoundEnvironment roundEnvironment) {
             // 一旦有类之上使用@Parameter注解
             if (!EmptyUtils.isEmpty(set)) {
                 // 获取所有被 @Parameter 注解的 元素(属性)集合
                 Set<? extends Element> elements = roundEnvironment.getElementsAnnotatedWith(Parameter.class);
     
                 if (!EmptyUtils.isEmpty(elements)) {
                     // 解析元素
                     try {
                         // 赋值临时map存储,用来存放被注解的属性集合
                         valueOfParameterMap(elements);
                         // 生成类文件,如:
                         createParameterFile();
                         return true;
                     } catch (IOException e) {
                         e.printStackTrace();
                     }
                 }
                 return true;
             }
             return false;
         }
     
         private void createParameterFile() throws IOException {
             // 判断是否有需要生成的类文件
             if (EmptyUtils.isEmpty(tempParameterMap)) return;
             // 通过Element工具类,获取Parameter类型
             TypeElement activityType = elementUtils.getTypeElement(Constants.ACTIVITY);
             TypeElement parameterType = elementUtils.getTypeElement(Constants.PARAMETER_LOAD);
     
             // 参数体配置(Object target)
             ParameterSpec parameterSpec = ParameterSpec.builder(TypeName.OBJECT, Constants.PARAMETER_NAMR).build();
             for (Map.Entry<TypeElement, List<Element>> entry : tempParameterMap.entrySet()) {
                 // Map集合中的key是类名,如:MainActivity
                 TypeElement typeElement = entry.getKey();
                 // 如果类名的类型和Activity类型不匹配
                 if (!typeUtils.isSubtype(typeElement.asType(), activityType.asType())) {
                     throw new RuntimeException("@Parameter注解目前仅限用于Activity类之上");
                 }
     
                 // 获取类名
                 ClassName className = ClassName.get(typeElement);
                 // 方法体内容构建
                 ParameterFactory factory = new ParameterFactory.Builder(parameterSpec)
                         .setMessager(messager)
                         .setClassName(className)
                         .build();
     
                 // 添加方法体内容的第一行
                 factory.addFirstStatement();
     
                 // 遍历类里面所有属性
                 for (Element fieldElement : entry.getValue()) {
                     factory.buildStatement(fieldElement);
                 }
     
                 // 最终生成的类文件名(类名$$Parameter)
                 String finalClassName = typeElement.getSimpleName() + Constants.PARAMETER_FILE_NAME;
                 messager.printMessage(Diagnostic.Kind.NOTE, "APT生成获取参数类文件:" +
                         className.packageName() + "." + finalClassName);
     
                 // MainActivity$$Parameter
                 JavaFile.builder(className.packageName(), // 包名
                         TypeSpec.classBuilder(finalClassName) // 类名
                                 .addSuperinterface(ClassName.get(parameterType)) // 实现ParameterLoad接口
                                 .addModifiers(Modifier.PUBLIC) // public修饰符
                                 .addMethod(factory.build()) // 方法的构建(方法参数 + 方法体)
                                 .build()) // 类构建完成
                         .build() // JavaFile构建完成
                         .writeTo(filer); // 文件生成器开始生成类文件
             }
         }
     
         /**
          * 赋值临时map存储,用来存放被@Parameter注解的属性集合,生成类文件时遍历
          *
          * @param elements 被 @Parameter 注解的 元素集合
          */
         private void valueOfParameterMap(Set<? extends Element> elements) {
             for (Element element : elements) {
                 // 注解在属性之上,属性节点父节点是类节点
                 TypeElement enclosingElement = (TypeElement) element.getEnclosingElement();
                 // 如果map集合中的key:类节点存在,直接添加属性
                 if (tempParameterMap.containsKey(enclosingElement)) {
                     tempParameterMap.get(enclosingElement).add(element);
                 } else {
                     List<Element> fields = new ArrayList<>();
                     fields.add(element);
                     tempParameterMap.put(enclosingElement, fields);
                 }
             }
         }
     }
    

生成方法体 ParameterFactory

    public class ParameterFactory {

        // MainActivity t = (MainActivity) target;
        private static final String CONTENT = "$T t = ($T)target";
    
        // 方法体构建
        private MethodSpec.Builder methodBuidler;
    
        // Messager用来报告错误,警告和其他提示信息
        private Messager messager;
    
        // 类名,如:MainActivity
        private ClassName className;
    
        private ParameterFactory(Builder builder) {
            this.messager = builder.messager;
            this.className = builder.className;
    
            // 通过方法参数体构建方法体:public void loadParameter(Object target) {
            methodBuidler = MethodSpec.methodBuilder(Constants.PARAMETER_METHOD_NAME)
                    .addAnnotation(Override.class)
                    .addModifiers(Modifier.PUBLIC)
                    .addParameter(builder.parameterSpec);
        }
    
        /**
         * 添加方法体内容的第一行(MainActivity t = (MainActivity) target;)
         */
        public void addFirstStatement() {
            // 方法内容:MainActivity t = (MainActivity) target;
            methodBuidler.addStatement(CONTENT, className, className);
        }
    
        public MethodSpec build() {
            return methodBuidler.build();
        }
    
        /**
         * 构建方体内容,如:t.s = t.getIntent.getStringExtra("s");
         *
         * @param element 被注解的属性元素
         */
        public void buildStatement(Element element) {
            // 遍历注解的属性节点 生成函数体
            TypeMirror typeMirror = element.asType();
            // 获取 TypeKind 枚举类型的序列号
            int type = typeMirror.getKind().ordinal();
            // 获取属性名
            String fieldName = element.getSimpleName().toString();
            // 获取注解的值
            String annotationValue = element.getAnnotation(Parameter.class).name();
            // 判断注解的值为空的情况下的处理(注解中有name值就用注解值)
            annotationValue = EmptyUtils.isEmpty(annotationValue) ? fieldName : annotationValue;
            // 最终拼接的前缀:
            String finalValue = "t." + fieldName;
            // t.s = t.getIntent().
            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 {
                // t.s = t.getIntent.getStringExtra("s");
                if (typeMirror.toString().equalsIgnoreCase(Constants.STRING)) {
                    methodContent += "getStringExtra($S)";
                }
            }
    
            // 健壮代码
            if (methodContent.endsWith(")")) {
                // 添加最终拼接方法内容语句
                methodBuidler.addStatement(methodContent, annotationValue);
            } else {
                messager.printMessage(Diagnostic.Kind.ERROR, "目前暂支持String、int、boolean传参");
            }
        }
    
        public static class Builder {
    
            // Messager用来报告错误,警告和其他提示信息
            private Messager messager;
    
            // 类名,如:MainActivity
            private ClassName className;
    
            // 方法参数体
            private ParameterSpec parameterSpec;
    
            public Builder(ParameterSpec parameterSpec) {
                this.parameterSpec = parameterSpec;
            }
    
            public Builder setMessager(Messager messager) {
                this.messager = messager;
                return this;
            }
    
            public Builder setClassName(ClassName className) {
                this.className = className;
                return this;
            }
    
            public ParameterFactory build() {
                if (parameterSpec == null) {
                    throw new IllegalArgumentException("parameterSpec方法参数体为空");
                }
    
                if (className == null) {
                    throw new IllegalArgumentException("方法内容中的className为空");
                }
    
                if (messager == null) {
                    throw new IllegalArgumentException("messager为空,Messager用来报告错误、警告和其他提示信息");
                }
    
                return new ParameterFactory(this);
            }
        }
    }
  1. 使用注解类

     @ARouter(path = "/order/OrderMainActivity")
     public class OrderMainActivity extends AppCompatActivity {
     
         @Parameter
         String name;
     
         @Parameter(name = "agex")
         int age;
     
         @Override
         protected void onCreate(@Nullable Bundle savedInstanceState) {
             super.onCreate(savedInstanceState);
             setContentView(R.layout.order_main_activity);
             
             //调用生成的类
             new OrderMainActivity$$Parameter().loadParameter(this);
         }
    
发布了98 篇原创文章 · 获赞 6 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/dirksmaller/article/details/103930775