ARouter是我弄组件化的时候用到的

因为组件化就保证了有不同的module,不同的module它都依赖于一个base_module。因为不同的module,所以我们没办法使用Intent进行跳转,于是使用了ARouter进行各个module之间的通信

我们可以在module于base_module之间添加一个路由模块,让这个路由模块来管理它们之间的路由

也就可以这么理解,以前的人们要把信件传递给别人,首先要把信件给邮局,然后邮局再把信给你要寄出去的那个人

这里邮局就是ARouter,它可以帮助相互没有依赖的组件进行跳转和通讯

1.ARouter的原理

ARouter在Activity中的跳转很简单,就是初始化ARouter,添加注解,发起路由

1:初始化ARouter// 在module app中
//1.初始化SDK
ARouter.init(mApplication); // 尽可能早,推荐在Application中初始化

2:添加注解// moduleA
// 2.在支持路由的页面上添加注解(必选)
// 路径注意至少需有两级,/xx/xx
@Route(path = "/test/activity")
public class YourActivity extend Activity {
  ...
}

3.发起路由跳转// moduleB(没有依赖 moduleA)
// 3.发起路由跳转
ARouter.getInstance().build("/test/activity").navigation();

其中@Route注解被称之为路由地址

ARouter的整个原理就是:ARouter通过Apt技术,生成保存路径(路由path)路由地址(Route)的一个映射关系的类,理由这些保存了映射关系的类,ARouter就可以根据用户的请求跳转到对应的目标地址

Apt将我们配置的注解与对应的Activity保存到一个Map中

就比如下面这样class RouterMap {
public Map getAllRoutes {
Map map = new HashMap<String,Class<?>>;
map.put("/test/activity",TestActivity.class);
map.put("/main/setting",SettingActivity.class);
map.put("/login/register",LoginRegisterActivity.class);
....

     return map;
}
}

然后将这个map加载到内存,需要的时候直接通过get(path)就可以了

2.APT的原理

刚才我们说了ARouter就是通过APT将我们写的注解和对应的Activity放到一个Map中,让后ARouter就是通过这个map进行的跳转

APT的作用就是在编译阶段扫描并处理代码中的注解,然后根据注解输出Java文件

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

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

2.1@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)

第一个@Target说实话不知道它是干嘛的,但是第二个@Retention这个还是得好好注意一下,表示下面的那个path要保留到编译的时候

3.ARouter的一个整体流程

我们在代码里加入的@Route注解,会在编译时期通过apt生成一些存储path和activityClass映射关系的类文件,然后app进程启动的时候会拿到这些类文件,把保存这些映射关系的数据读到内存里(保存在map里),然后在进行路由跳转的时候,通过build()方法传入要到达页面的路由地址,ARouter会通过它自己存储的路由表找到路由地址对应的Activity.class(activity.class = map.get(path)),然后new Intent(),当调用ARouter的withString()方法它的内部会调用intent.putExtra(String name, String value),调用navigation()方法,它的内部会调用startActivity(intent)进行跳转,这样便可以实现两个相互没有依赖的module顺利的启动对方的Activity了。

我稍微简化一下就是,@Route这个我们在上面讲过,就是它会在将你注解写的那个路径一直保存在编译的时候,在编译的时候通过apt生成存储path和activityClass的一个map,当app进程启动的时候会通过这个map把这个map读到内存里面,在路由跳转也就是的时候,通过build传入你的那个注解比如/test/activity。然后在内存的map中找到这个注解对应的activityclass,然后new Intent(),

当你想通过ARouter再传些值的时候再调用ARouter.withString()方法,它其实就是在内部调用了Intent.putExtra()

调用navigation()会在内部调用startActivity

就是

当你ARouter.build(xxxx)的时候就是new Intent()

当你ARouter.withString()的时候就是Intent.putExtra()

当你ARouter.navigation()的时候就是Intent.startActivity()

3.1添加注解

在使用ARouter的时候,你首先先得给你需要跳转的Activity或者Fragment等类的前面添加注解,注明他的路径。添加注解的时候,ARouter就会根据你添加的注解通过APT自动生成对应的三个类:Group、Providers、Root。

  1. Group 类:生成的 Group 类是根据路径中的分组信息生成的,用于路由的分组管理。每个 Group 类都包含一个静态的 loadInto(Map<String, Class<? extends IRoute>> routes) 方法,在该方法中将目标类与路径进行关联。
  2. Providers 类:生成的 Providers 类用于存储路径对应的具体类的信息
  3. Root 类:生成的 Root 类是整个路由框架的入口类,用于初始化路由框架。Root 类中包含一个静态的 loadInto(Map<String, Class<? extends IRoute>> routes) 方法,在该方法中会加载所有生成的 Group 类并注册路由信息。

简单记忆就是

Root类是路由的初始化

Group是路径的分组

Providers是存储路径和类(就是Activity.class)的映射关系

3.2初始化

当你调用ARouter的init方法时,他就会有一个类叫Warehouse,这个类里面只有3组也就是6个静态类型的Map,对应着我们刚刚说的APT自动生成的那三个类,分别是route的map、provider的map以及拦截器Interceptor的map

然后init就会拿到所有配置了route的类,按照不同的属性分别加到三个map里面去。

调用init方法后会调用_ARouter的afterinit方法,这个方法最后会返回一个根据path和group来new好的一个Postcard对象,这个Postcard就是用来存放跳转所需信息,也就是说我们在通过ARouter传值的时候,设定的值都先放在这个Postcard里面

3.2.1注意:

Interceptor的好理解,它就是存拦截器的

那么另外两个呢?

Route是用来存跳转的界面的那个注解和跳转界面的activity.class

但是Provider是存的是注解和你要跳转的Service的

3.3跳转

然后当我们需要跳转的时候,实际上调用的是ARouter的navigation方法,在这个方法中就会new一个intent,然后把postcard中存储的activity传进去,接着如果你配置了Extra,就会调用intent的putExtra方法把postcard中的Extra给传进去,同样的,如果你设置了Flag也是把postcard的Flag传给intent,action也是从postcard传给intent。等extra、flag、action都配置好了之后,就通过runInMainThread回到主线程然后调用startActivity跳转过去。

其中runInMainThread是通过得到主线程的Looper,再判断当前线程是不是主线程,如果不是就通过handler发消息,如果是就直接run。startActivity也是_ARouter自己的方法,基本上都是通过ActivityCompat调用startActivityForResult或者startActivity进行跳转。

就是调用navigation就会把postCard中保存的参数全部传给Intent,然后都配置好后通过runInMainThread回到主线程然后调用startActivity跳转过去


一沙一世界,一花一天堂。君掌盛无边,刹那成永恒。