Android架构师-组件化-组件化路由架构设计 6

一:思考: 在组件化架构中,我们需要通过APT和JavaPoet技术生成什么样的类文件呢

组件化路由架构设计图:

Android架构师-组件化-组件化路由架构设计 6_第1张图片

 

思考:

1:为什么要组名,为什么不直接通过path路径来取Class类对象呢

    例如:组名app   组名order  组名personal

 比如组名有:

 app  :那么对应的路径的详细的Class类文件,那么这个文件就是ARouter$Path$$app,都是APT生成的,是一对一的关系

 而组对应的详细路径列表中又是一对多 ,比如  MainActivity1,MainActivity2....就是详细的路径作为Key,而value就是详细的类     对  象,是一对多的关系

  我们可以模拟一个这样的场景,当用户进入首页,什么都没有做,点错了,然后点退出,然后在app的子模块中有50个Activity,在order的子模块汇总有30个Acticity,我们就有80个Activity需要加载到内存中来,如果我们进入首页只给他加载5个Activity就足够了呢?

所以我们分组的目的就是节省内存,提高性能。

2:生成这些文件干嘛用?

这些文件我们可以通过path的一个路径得到一个Class的类对象,最终完成交互。

那我们从之前(上篇文章)的一个module到现在的N个module是不是一样的呢?

是一样的,只不过我们传的path,从里面截取出来一个组名,然后通过组名找到对应的Class文件,也就是ARout$$Group$$app,r然后再拿完整的path路径去匹配具体的类文件。

然后完成子模块间的交互

二:RouterBean对象

  之前我们建立过PathBean对象,有两个属性,一个是String 类型的path  一个是Class类型的 类文件

这个RouterBean就是把它拓展了,比如

Android架构师-组件化-组件化路由架构设计 6_第2张图片

group是从path中截取的。

三:ARouterLoadGroup接口

Android架构师-组件化-组件化路由架构设计 6_第3张图片

Android架构师-组件化-组件化路由架构设计 6_第4张图片

接口的方式更加容易和好拓展。

四:组件化项目部署

Android架构师-组件化-组件化路由架构设计 6_第5张图片

有5个方面

1:就是上面的两个接口

2:公共基础库,比如我们前面有app ,order ,personal 都引用了这个库,所以只要我们在其中穿插进ARouter API,中间就可以做中转的作用。

4:使用APT生成的代码完成交互

五:撸代码:

1:按照上文的步骤,我们先创建一个arouter_api

Android架构师-组件化-组件化路由架构设计 6_第6张图片

/**
 * 路由组Group加载数据接口
 */
public interface ARouterLoadGroup {

    /**
     * 加载路由组Group数据
     * 比如:"app", ARouter$$Path$$app.class(实现了ARouterLoadPath接口)
     *
     * @return key:"app", value:"app"分组对应的路由详细对象类
     */
    Map> loadGroup();
}
/**
 * 路由组Group对应的详细Path加载数据接口
 * 比如:app分组对应有哪些类需要加载
 */
public interface ARouterLoadPath {

    /**
     * 加载路由组Group中的Path详细数据
     * 比如:"app"分组下有这些信息:
     *
     * @return key:"/app/MainActivity", value:MainActivity信息封装到RouterBean对象中
     */
    Map loadPath();
}

首先创建自定义注解和注解处理器

通过构建者模式创建实体封装类

/**
 * 路由路径Path的最终实体封装类
 * 比如:app分组中的MainActivity对象,这个对象有更多的属性
 */
public class RouterBean {

    public enum Type {
        ACTIVITY
    }

    // 枚举类型:Activity
    private Type type;
    // 类节点
    private Element element;
    // 注解使用的类对象
    private Class clazz;
    // 路由地址
    private String path;
    // 路由组
    private String group;

    private RouterBean(Builder builder) {
        this.type = builder.type;
        this.element = builder.element;
        this.clazz = builder.clazz;
        this.path = builder.path;
        this.group = builder.group;
    }

    private RouterBean(Type type, Class clazz, String path, String group) {
        this.type = type;
        this.clazz = clazz;
        this.path = path;
        this.group = group;
    }

    // 对外提供简易版构造方法,主要是为了方便APT生成代码
    public static RouterBean create(Type type, Class clazz, String path, String group) {
        return new RouterBean(type, clazz, path, group);
    }

    public Type getType() {
        return type;
    }

    public void setType(Type type) {
        this.type = type;
    }

    public Element getElement() {
        return element;
    }

    public void setElement(Element element) {
        this.element = element;
    }

    public Class getClazz() {
        return clazz;
    }

    public void setClazz(Class clazz) {
        this.clazz = clazz;
    }

    public String getPath() {
        return path;
    }

    public void setPath(String path) {
        this.path = path;
    }

    public String getGroup() {
        return group;
    }

    public void setGroup(String group) {
        this.group = group;
    }

    /**
     * 构建者模式
     */
    public static class Builder {

        // 枚举类型:Activity
        private Type type;
        // 类节点
        private Element element;
        // 注解使用的类对象
        private Class clazz;
        // 路由地址
        private String path;
        // 路由组
        private String group;

        public Builder setType(Type type) {
            this.type = type;
            return this;
        }

        public Builder setElement(Element element) {
            this.element = element;
            return this;
        }

        public Builder setClazz(Class clazz) {
            this.clazz = clazz;
            return this;
        }

        public Builder setPath(String path) {
            this.path = path;
            return this;
        }

        public Builder setGroup(String group) {
            this.group = group;
            return this;
        }

        // 最后的build或者create,往往是做参数的校验或者初始化赋值工作
        public RouterBean build() {
            if (path == null || path.length() == 0) {
                throw new IllegalArgumentException("path必填项为空,如:/app/MainActivity");
            }
            return new RouterBean(this);
        }
    }

    @Override
    public String toString() {
        return "RouterBean{" +
                "path='" + path + '\'' +
                ", group='" + group + '\'' +
                '}';
    }
}
@Target(ElementType.TYPE) // 该注解作用在类之上
@Retention(RetentionPolicy.CLASS) // 要在编译时进行一些预处理操作,注解会在class文件中存在
public @interface ARouter {

    // 详细路由路径(必填),如:"/app/MainActivity"
    String path();

    // 路由组名(选填,如果开发者不填写,可以从path中截取出来)
    String group() default "";
}

 

/**
 * 常量类
 */
public class Constants {

    // 注解处理器中支持的注解类型
    public static final String IROUTER_ANNOTATION_TYPES = "com.netease.arouter.annotation.ARouter";
}

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

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

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

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

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

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

    }

    /**
     * 相当于main函数,开始处理注解
     * 注解处理器的核心方法,处理具体的注解,生成Java文件
     *
     * @param set              使用了支持处理注解的节点集合
     * @param roundEnvironment 当前或是之前的运行环境,可以通过该对象查找的注解。
     * @return true 表示后续处理器不会再处理(已经处理完成)
     */
    @Override
    public boolean process(Set set, RoundEnvironment roundEnvironment) {
        return false;
    }
}

但是我们看到这progress里面没有处理,我们需要使用ARouter_api里面的加载数据接口。

// 每个功能子模块既然都要生成APT源文件,而且又是所有模块依赖的公共库
// 那么公共基础库依赖路由arouter_api就能向每个子模块提供开放api了

所以在公共库的build.gradle中需要依赖arouter_api

 api project(':arouter_api') // 路由对外开放api模块

所以将处理逻辑放到common中。

我们模拟一个想要的路由器组文件

Android架构师-组件化-组件化路由架构设计 6_第7张图片AA

先从传入的路径中截取group信息 返回的是 Map> 一个map集合,path是路径,返回值是ARouterLoadPath对象

/**
 * 模拟ARouter路由器的组文件
 */
public class ARouter$$Group$$order implements ARouterLoadGroup {

    @Override
    public Map> loadGroup() {
        Map> groupMap = new HashMap<>();
        groupMap.put("order", ARouter$$Path$$order.class);
        return groupMap;
    }
}

 

//我们通过路由组中的path详细数据,可以得到RouterBean对象,里面包含group,path,Class对象等信息

/**
 * 路由组Group对应的详细Path加载数据接口
 * 比如:app分组对应有哪些类需要加载
 */
public interface ARouterLoadPath {

    /**
     * 加载路由组Group中的Path详细数据
     * 比如:"app"分组下有这些信息:
     *
     * @return key:"/app/MainActivity", value:MainActivity信息封装到RouterBean对象中
     */
    Map loadPath();
}

我们在common建立一个管理类,用来将Activity添加到两个集合中:group集合,path集合

/**
 * 全局路径记录器(根据子模块分组)
 */
public class RecordPathManager {

    // key:"order"组     value:order子模块下,对应所有的Activity路径信息
    private static Map> groupMap = new HashMap<>();

    /**
     * 将路径信息加入全局Map
     *
     * @param groupName 组名,如:"personal"
     * @param pathName  路劲名,如:"Personal_MainActivity"
     * @param clazz     类对象,如:Personal_MainActivity.class
     */
    public static void joinGroup(String groupName, String pathName, Class clazz) {
        List list = groupMap.get(groupName);
        if (list == null) {
            list = new ArrayList<>();
            list.add(new PathBean(pathName, clazz));
            groupMap.put(groupName, list);
        } else {
            groupMap.put(groupName, list);
        }
        groupMap.put(groupName, list);
    }

    /**
     * 根据组名和路径名获取类对象,达到跳转目的
     *
     * @param groupName 组名
     * @param pathName  路径名
     * @return 跳转目标的class类对象
     */
    public static Class getTargetClass(String groupName, String pathName) {
        List list = groupMap.get(groupName);
        if (list == null) return null;
        for (PathBean path : list) {
            if (pathName.equalsIgnoreCase(path.getPath())) {
                return path.getClazz();
            }
        }
        return null;
    }

    /**
     * 清理、回收
     */
    public static void recycleGroup() {
        groupMap.clear();
        groupMap = null;
        System.gc();
    }

}

在哪里调用呢?

在app中:


public class AppApplication extends BaseApplication {

    @Override
    public void onCreate() {
        super.onCreate();
        // 如果项目有100个Activity,这种加法会不会太那个?
        RecordPathManager.joinGroup("app", "MainActivity", MainActivity.class);
        RecordPathManager.joinGroup("order", "Order_MainActivity", Order_MainActivity.class);
        RecordPathManager.joinGroup("personal", "Personal_MainActivity", Personal_MainActivity.class);
    }
}

 

 

 

 

你可能感兴趣的:(Android架构师-组件化-组件化路由架构设计 6)