行业知识
Android学习之路(24) ARouter原理解析
1.ARouter认知
首先我们从命名来看:ARouter翻译过来就是一个路由器。
官方定义:
一个用于帮助 Android App 进行组件化改造的框架 —— 支持模块间的路由、通信、解耦
那么什么是路由呢? 简单理解就是:一个公共平台转发系统
工作方式:
- 1.注册服务:将我们需要对外暴露的页面或者服务注册到ARouter公共平台中
- 2.调用服务:调用ARouter的接口,传入地址和参数,ARouter解析传入的地址和参数转发到对应的服务中
通过ARouter形成了一个无接触解耦的调用过程
2.ARouter架构解析
我们来看下ARouter的源码架构:
- app:是ARouter提供的一个测试Demo
- arouter-annotation:这个lib模块中声明了很多注解信息和一些枚举类
- arouter-api:ARouter的核心api,转换过程的核心操作都在这个模块里面
- arouter-compiler:APT处理器,自动生成路由表的过程就是在这里面实现的
- arouter-gradle-plugin:这是一个编译期使用的Plugin插件,主要作用是用于编译器自动加载路由表,节省应用的启动时间。
3.原理讲解
这里我们不会一开始就大篇幅对源码进行讲解: 我们先来介绍ARouter中的几个重要概念:有了这几个概念,后面在去看源码就会轻松多了
前置基础概念:
概念1:PostCard(明信片)
既然是明信片要将信件寄到目的人的手上就至少需要:收件人的姓名和地址,寄件人以及电话和地址等
ARouter就是使用PostCard这个类来存储寄件人和收件人信息的。
java复制代码public final class Postcard extends RouteMeta { // Base private Uri uri; //如果使用Uri方式发起luyou private Object tag; // A tag prepare for some thing wrong. inner params, DO NOT USE! private Bundle mBundle; // 需要传递的参数使用bundle存储 private int flags = 0; // 启动Activity的标志:如NEW_FALG private int timeout = 300; // 路由超时 private IProvider provider; // 使用IProvider的方式跳转 private boolean greenChannel;//绿色通道,可以不经过拦截器 private SerializationService serializationService; //序列化服务serializationService:需要传递Object自定义类型对象,就需要实现这个服务 private Context context; // May application or activity, check instance type before use it. private String action;//Activity跳转的Action // Animation private Bundle optionsCompat; // The transition animation of activity private int enterAnim = -1; private int exitAnim = -1;...}PostCard继承了RouteMeta:
java复制代码public class RouteMeta { private RouteType type; // 路由类型:如Activity,Fragment,Provider等 private Element rawType; // 路由原始类型,在编译时用来判断 private Class destination; // 目的Class对象 private String path; // 路由注册的path private String group; // 路由注册的group分组 private int priority = -1; // 路由执行优先级,priority越低,优先级越高,这个一般在拦截器中使用 private int extra; // Extra data private Map paramsType; // 参数类型,例如activity中使用@Autowired的参数类型 private String name; //路由名字,用于生成javadoc private Map injectConfig; // 参数配置(对应paramsType).}RouteMeta:主要存储的是一些目的对象的信息,这些对象是在路由注册的时候才会生成。
概念2:Interceptor拦截器
了解OkHttp的都知道,其内部调用过程就是使用的拦截器模式,每个拦截器执行的对应的任务。
而ARouter中也是如此,所有的路由调用过程在到达目的地前都会先经过自定义的一系列拦截器,实现一些AOP切面编程。
java复制代码public interface IInterceptor extends IProvider { /** * The operation of this interceptor. * * @param postcard meta * @param callback cb */ void process(Postcard postcard, InterceptorCallback callback);}IInterceptor是一个接口,继承了IProvider,所以其也是一个服务类型
只需要实现process方法就可以实现拦截操作。
概念3:greenChannel:绿色通道
设置了绿色通道的跳转过程,可以不经过拦截器
概念4:Warehouse:路由仓库
Warehouse意为仓库,用于存放被 @Route、@Interceptor注释的 路由相关的信息,也就是我们关注的destination等信息
举个例子:
moduleB发起路由跳转到moduleA的activity,moduleB没有依赖moduleA,只是在moduleA的activity上增加了@Route注解。 由于进行activity跳转需要目标Activity的class对象来构建intent,所以必须有一个中间人,把路径"/test/activity"翻译成Activity的class对象,然后moduleB才能实现跳转。(因此在ARouter的使用中 moduleA、moduleB 都是需要依赖 arouter-api的)
这个中间人那就是ARouter了,而这个翻译工所作用到的词典就是Warehouse,它存着所有路由信息。
java复制代码class Warehouse { //所有IRouteGroup实现类的class对象,是在ARouter初始化中赋值,key是path第一级 //(IRouteGroup实现类是编译时生成,代表一个组,即path第一级相同的所有路由,包括Activity和Provider服务) static Map fragmentMeta = postcard.getDestination();try {Object instance = fragmentMeta.getConstructor().newInstance();if (instance instanceof Fragment) {((Fragment) instance).setArguments(postcard.getExtras());} else if (instance instanceof android.support.v4.app.Fragment) {((android.support.v4.app.Fragment) instance).setArguments(postcard.getExtras());}return instance;} catch (Exception ex) {logger.error(Consts.TAG, "Fetch fragment instance error, " + TextUtils.formatStackTrace(ex.getStackTrace()));}case METHOD:case SERVICE:default:return null;}return null;}这个方法其实就是根据PostCard的type来处理不同的请求了
- 1.Activity,直接跳转
- 2.Fragment,Provider,BroadcaseReceiver和ContentProvider,直接返回类的实例对象。
整个过程我们就基本了解了。 上面还留了一个点:
留的点1:ARouter是如何完善PostCard信息
看LogisticsCenter.completion(postcard);
进入这个方法:
java复制代码public synchronized static void completion(Postcard postcard) { if (null == postcard) { throw new NoRouteFoundException(TAG + "No postcard!"); }//去Warehouse.routes去取路由元数据,开始肯定是没有的 RouteMeta routeMeta = Warehouse.routes.get(postcard.getPath());//没获取到 if (null == routeMeta) { // Maybe its does't exist, or didn't load.//判断Warehouse.groupsIndex路由组中是否有这个group if (!Warehouse.groupsIndex.containsKey(postcard.getGroup())) { throw new NoRouteFoundException(TAG + "There is no route match the path [" + postcard.getPath() + "], in group [" + postcard.getGroup() + "]"); } else { try { //动态添加路由元信息到路由中 addRouteGroupDynamic(postcard.getGroup(), null); } catch (Exception e) { }//重新加载。这个时候就会有路由元信息了 completion(postcard); // Reload } } else {//给postcard设置目的地,设置类型,设置优先级,设置Extra等信息 postcard.setDestination(routeMeta.getDestination()); postcard.setType(routeMeta.getType()); postcard.setPriority(routeMeta.getPriority()); postcard.setExtra(routeMeta.getExtra()); Uri rawUri = postcard.getUri(); ... switch (routeMeta.getType()) { case PROVIDER: // if the route is provider, should find its instance // Its provider, so it must implement IProvider Class
上一篇:怎么保存服务器数据到手机?
下一篇:git本地服务器怎么搭建?