Android组件化实战六:路由架构设计

Android 组件化实战一: Gradle基础语法
Android 组件化实战二: 项目部署
Android组件化实战三: 模块之间的交互
Android组件化实战四: APT的介绍与使用
Android组件化实战五: APT的高级用法JavaPoet
Android组件化实战六:路由架构设计

前言

结合前面的模块之间的交互,主要分析了类加载、全局Map记录(跳转目标Class)两种交互方式,以及APT和JavaPoet技术生成类文件,本文分析组件化的路由架构,我们到底需要通过APT和JavaPoet生成什么样的类文件呢?

组件化路由架构设计

在这里插入图片描述

先来看这样一幅架构设计图,组文件记录是一对一的即一个子模块对应一个组文件记录,而一个组文件记录对应多个路径文件记录,第二点比较好理解,因为各个子模块有多个Activity,对应多个路径信息。对应第一点,为什么要生成一对一的组(名)文件记录呢?试想一下,如果用户进入首页,没有进行后续操作,退出应用。而我们还像之前分析的,在application中将全部的activity对应的路径信息记录到Map集合,加载到内存,这显然是不合理的,出于性能优化(内存优化)的考虑,只有用到对应组(模块)时,才去保存对应模块下Activity的路径信息。所以才会根据组(模块)名,生成对应的文件记录。要通过APT和JavaPoet生成哪些类文件呢?

RouterBean对象

在前面的文章中通过全局Map记录方案实现子模块交互时,有涉及到PathBean对象,主要包含目标Activity的路径path,和Class属性。获取class属性,即可实现交互(跳转)。而RouterBean对象就是在PathBean的基础上进行了扩展:

public class RouterBean {
   

    // 枚举,现在只是处理作用在Activity上的注解
    // 后续还会扩展处理接口上的注解
    public enum Type{
   
        ACTIVITY
    }

    //枚举类型
    private Type type;
    //类节点
    private Element element;
    //路由的组名,从path "/app/MainActivity" 截取app作为组名
    private String group;
    //路由的地址
    private String path;
    //被@ARouter注解的类对象
    private Class<?> clazz;


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

Element类节点为什么也要存起来?

  • 因为将来我们要在注解处理器中,循环拿到每个类节点,方便赋值和调用
  • Element它是javax.lang包下的,不属于Android Library

ARouterLoadGroup接口

/**
 * 路由组group对外提供加载数据接口
 */
public interface ARouterLoadGroup {
   

    /**
     * 加载路由组group数据
     * 比如:"app", ARouter$$Path$$app.class(实现了ARouterLoadPath接口)
     * @return key: "app"即组名, value: "app"分组对应的路由详细对象类
     */
    Map<String, Class<? extends ARouterLoadPath>> loadGroup();
}

Map<String, Class<? extends ARouterLoadPath>>

  • 需要生成路由路径文件后,才能生成路由组文件
  • 接口方式容易拓展、通用

ARouterLoadPath接口

/**
 * 路由组group对应的详细path加载数据接口
 * 比如:app分组对应有哪些类需要加载
 */
public interface ARouterLoadPath{
   
    /**
     * 加载路由组group中的path详细数据
     * 比如:app分组下有这些信息
     * @return key: "app/MainActivity", value:MainActivity信息封装到RouterBean对象中
     */
    Map<String, RouterBean> loadPath();
}

Map<String, RouterBean>

  • OOP思想,让单纯的targetClass变成更灵活的RouterBean对象
  • 接口方式容易拓展、通用
路由框架部署步骤
  • 配置arouter_api/build.gradle
  • 配置common(公共基础库)/build.gradle
  • 完成模拟APT生成的类代码
  • app子模块中,模拟跳转代码
  • 演示跳转

相关的配置问题可以参考前面的文章和文末代码链接查看。这里重点介绍模拟生成的类文件中的逻辑,以及跳转逻辑。在app模块中新建一个目录test,存放模拟apt生成的文件,就是自己手动创建的,主要是为了对流程进行说明,后续会通过apt来生成文件。不同模块对应文件中的逻辑是一样的

在这里插入图片描述

在这里插入图片描述

/**
 * 模拟ARouter路由器的组文件
 */
public class ARouter$$Group$$order implements ARouterLoadGroup {
   
    @Override
    public Map<String, Class<? extends ARouterLoadPath>> loadGroup() {
   
        // key: 组名,value: 分组对应的路由详细对象类
        Map<String, Class<? extends ARouterLoadPath>> groupMap = new HashMap<>();
        groupMap.put("order", ARouter$$Path$$order.class);
        return groupMap;
    }
}

返回的是map集合,key表示组名比如order,value表示分组(即模块)对应路由详细对象类

/**
 * 模拟ARouter路由器的组文件对应的路径
 */
public class ARouter$$Path$$order implements ARouterLoadPath {
   

    @Override
    public Map<String, RouterBean> loadPath() {
   
        Map<String, RouterBean> pathMap = new HashMap<>();
        pathMap.put("/order/Order_MainActivity",
                RouterBean.create(RouterBean.Type.ACTIVITY, Order_MainActivity.class,
                        "/order/Order_MainActivity", "order"));
        return pathMap;
    }
}

返回的是map集合,key表示路径信息,value表示将目标Activity的信息封装到RouterBean对象,可以从中获取对应的class对象。如果这部分不是很理解,看了跳转逻辑,应该就比较清晰了。

在app的MainActivity中,跳转逻辑如下:

public void jumpOrder(View view) {
   
    /*Intent intent = new Intent(this, OrderActivity.class);
    intent.putExtra("name", "xpf");
    startActivity(intent);*/

    // 模拟APT生成的类文件,实现跳转
    ARouterLoadGroup loadGroup = new ARouter$$Group$$order();
    // 只会加载order模块Activity对应的类对象到内存,避免将所有模块的Activity对应的类对象加载到内存
    // 这就是处于性能优化(准确的说是内存优化),要有分组保存、获取的原因
    Map<String, Class<? extends ARouterLoadPath>> groupMap = loadGroup.loadGroup();
    // app--->order
    Class<? extends ARouterLoadPath> clazz = groupMap.get("order");
    try {
   
        ARouterLoadPath path = clazz.newInstance();
        Map<String, RouterBean> pathBean 
  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值