您当前的位置: 首页 >  ar

ARouter原理解析

发布时间:2020-08-09 15:54:52 ,浏览量:5

一、ARouter概述

用简单一两句话总结出来:ARouter通过Apt技术,生成保存路径(路由path)和被注解(@Router)的组件类的映射关系的类,利用这些保存了映射关系的类,Arouter根据用户的请求postcard(明信片)寻找到要跳转的目标地址(class),使用Intent跳转。原理很简单,可以看出来,该框架的核心是利用apt生成的映射关系。

使用时,在每个需要对其他module提供调用的Activity中,都要声明类似下面@Route注解,我们称之为路由地址。

@Route(path = "/main/homepage")
public class HomeActivity extends BaseActivity {
		onCreate()
		....
}

然后在需要跳转的时候调用

Arouter.getInstance().build("main/hello").navigation;

这里的路径“main/hello”是用户唯一配置的东西,我们需要通过这个path找到对应的Activity。最简单的思路就是通过APT技术,寻找到所有带有注解@Router的组件,将其注解值path和对应的Activity保存到一个map里,比如像下面这样:

class RouterMap {
	 public Map getAllRoutes {
	 		Map map = new HashMap

然后在工程代码中将这个map加载到内存中,需要的时候直接get(path)就可以了。

这样,两个模块不用相互有任何直接的依赖,就可以进行转跳,模块与模块之间就相互独立了。

二、APT原理

ARouter的使用非常方便,得益于APT。APT的作用是在编译阶段扫描并处理代码中的注解,然后根据注解输出Java文件。

ARouter为了方便实现注解处理器还额外用了两个库。

  • 一个是JavaPoet,他提供了调用对象方法的方式生成需要的代码,而不再需要人为的用StringBuilder去拼接代码,再使用IO写入文件。
  • 一个是Auto-Service,他提供了简便的方式去注册APT,避免了原本繁琐的注册步骤。
@Route

Route的定义是注解:

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.CLASS)
public @interface Route{
    /**
     * Path of route
     */
    String path();
    ……
}
  • @Target({ElementType.TYPE})——表示这个annotation是修饰类的
  • @Retention(RetentionPolicy.CLASS)——表示需要保留到编译时

Route中有一个主要的参数path,他表示了Activity的路由地址。

@Route(path = RouteHub.QRCode.QRCODE_SCAN_PATH)

这样编译时能获取到Route所注解的类,并且能获取到path路径。

RouteProcessor

RouteProcessor是对@Route注解的处理的地方。

@AutoService(Processor.class)
@SupportedAnnotationTypes({ANNOTATION_TYPE_ROUTE, ANNOTATION_TYPE_AUTOWIRED})
public class RouteProcessor extends BaseProcessor

解释:

  • auto-service——这个库为Processor完成了自动注册
  • @SupportedAnnotationTypes({ANNOTATION_TYPE_ROUTE, ANNOTATION_TYPE_AUTOWIRED})——表明了当前Processor是出里那些注释的

RouteProcessor继承于BaseProcessor,在init方法中获取到了每个模块的moduleName。

// Attempt to get user configuration [moduleName]
Map options = processingEnv.getOptions();
if (MapUtils.isNotEmpty(options)) {
  moduleName = options.get(KEY_MODULE_NAME);
  …………
}

RouteProcessor的process方法是对注解处理的地方,它直接获取了所有Route注解的元素。

Set routeElements = roundEnv.getElementsAnnotatedWith(Route.class);

拿到被标注的元素后就会进入this.parseRoutes(routeElements);方法。这个方法使用JavaPoet生成Java文件。如果不用这个库我们也可以使用StringBuilder去写Java文件的内容。

process

回过头来再看RouteProcessor的process方法:

public boolean process(Set annotations, RoundEnvironmentroundEnv) {
  if(CollectionUtils.isNotEmpty(annotations)) {
    //获取所有Route注解元素
    SetrouteElements = roundEnv.getElementsAnnotatedWith(Route.class);
    try {
      this.parseRoutes(routeElements);
    } catch (Exception e) {
      logger.error(e);
    }
    return true;
  }
  return false;
}

process方法将所有的Route注解元素放进了parseRoutes方法用于生成IRouteGroup和IRouteRoot。这里面使用JavaPoet提供的类,通过方法调用的形式生成代码。

三、路由文件、跳转原理

上面利用APT、JavaPoet完成了代码生成的工作,对于一个大型项目,组件数量会很多,可能会有一两百或者更多,把这么多组件都放到这个Map里,显然会对内存造成很大的压力,因此,Arouter采用的方法就是“分组+按需加载”,分组还带来的另一个好处是便于管理,下面我们来看一下实现原理。

解决步骤一:分组

首先看如何分组的,Arouter在一层map之外,增加了一层map,我们看WareHouse这个类,里面有两个静态Map:

static Map            
关注
打赏
1688896170
查看更多评论

暂无认证

  • 5浏览

    0关注

    115984博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文
立即登录/注册

微信扫码登录

0.0466s