ARouter源码分析

32 阅读4分钟

一、简介

ARouter是一个路由框架,主要用于解决模块化场景后的模块间通信问题而设计的

ARouter的优势:

  • 优势一:直接解析URL路由,解析参数并赋值到对应目标字段的页面中。
  • 优势二:支持多模块项目,因为现在很少有APP是单模块的项目,一般都是多模块单工程的,由不同的团队负责不同的模块开发,这时候支持多模块项目开发就显得尤为重要。
  • 优势三:支持InstantRun,目前很多路由框架并不支持InstantRun,而InstantRun是Google在AndroidStudio2.0阿尔法版本中提供的新功能,其类似于代码的日更新,其只不过面向的是开发过程,这样做可以在开发的过程中减少开发和编译的次数,可以简单地将代码修改即时地同步到APK中,从而可以大规模降低开发复杂度。
  • 优势四:允许自定义拦截器,ARouter是支持拦截器的,而拦截器其实就是AOP的实现,可以自定义多个拦截器解决一些面向行为编程上出现的问题。
  • 优势五:ARouter可以提供IoC容器,IoC其实就是控制反转,这一部分做过服务端开发的朋友可能比较了解,因为服务端开发经常用到的Spring框架能够提供的一个非常重要的能力就是控制反转。
  • 优势六:映射关系自动注册,在页面不是很多的小型APP上面,自动注册并不会体现出太大优势,但是对于大型APP而言,可能页面数量已经达到的几十个或者数百个,在这样的情况下,自动注册就显得非常重要了,因为不可能将每一个页面都通过代码的方式进行注册。
  • 优势七:灵活的降级策略,ARouter可以提供很多种降级策略供用户自行选择,而原生的路由方案存在无法灵活降级的问题,StartActivity()一旦失败将会抛出运营级异常。

二、整体流程图

348489410cab86f9f2629c17a8787df8.png

三、概念解释

RouteMeta:路由元信息,即基础信息。理解就是 明信片上的 收件人地址 这种必备的基础信息。明信片上可以没有文字内容,但想要被邮寄就必须有收件人地址。

Postcard:路由的信息。理解为是生活中的明信片。继承自RouteMeta。例如Postcard中的mBundle等则是 明信片上寄件人写的 “你好,xxx 节日快乐!” 这种文字内容。

WareHorse:信息中心,各类路由信息的存储中心。

四、流程

Postcard postcard = ARouter.getInstance().build(AppRouter.LauncherActivity.PATH);
postcard.navigation(context);
整体流程就分为两步:

获取postcard:

    • 前置拦截处理:PathReplaceService,看看是否需要变换路由地址,不需要就创建一个postcard

    • 完善postcard信息:通过LogisticsCenter.completion方法,获取RouteMeta完善postcard信息(分组加载:获取RouteMeta,不存在时,说明该组第一次使用,此时将组加载到Warehouse.routes中去)

    • 后置绿色通道处理:provider、fragment 默认会走绿色通道,正常其他的路由,需要走非绿色通过逻辑,提供一次拦截能力

使用postcard去路由:例如进行目标Activity的跳转、获取IProvider实现对象、获取Fragment等。

五、核心代码

可见,postcard 经过完善后,路由类型type、目的地destination等都已经被赋了值。destination就是目标类的class对象。

方法内容就是根据路由类型来走对应逻辑:

  • Activity, 使用postcard.getDestination()来构建intent、传入Extras、设置 flags、action,最后在主线程执行 熟悉的startActivity
  • provider,指的是想要获取的服务,即IProvider的实现类。是直接从postCard中获取的,因为服务类是单例,只会在首次获取时创建()。
  • Broadcast、ContentProvider、Fragment,都是使用postcard.getDestination()反射创建实例
private Object _navigation(final Postcard postcard, final int requestCode, final NavigationCallback callback) {
        final Context currentContext = postcard.getContext();
        switch (postcard.getType()) {
            case ACTIVITY:
                final Intent intent = new Intent(currentContext, postcard.getDestination());
                intent.putExtras(postcard.getExtras());
                int flags = postcard.getFlags();
                if (0 != flags) {
                    intent.setFlags(flags);
                }

                if (!(currentContext instanceof Activity)) {
                    intent.addFlags(268435456);
                }

                String action = postcard.getAction();
                if (!TextUtils.isEmpty(action)) {
                    intent.setAction(action);
                }

                this.runInMainThread(new Runnable() {
                    public void run() {
                        _ARouter.this.startActivity(requestCode, currentContext, intent, postcard, callback);
                    }
                });
                return null;
            case PROVIDER:
                return postcard.getProvider();
            case BOARDCAST:
            case CONTENT_PROVIDER:
            case FRAGMENT:
                Class<?> fragmentMeta = postcard.getDestination();

                try {
                    Object instance = fragmentMeta.getConstructor().newInstance();
                    if (instance instanceof Fragment) {
                        ((Fragment)instance).setArguments(postcard.getExtras());
                    } else if (instance instanceof androidx.fragment.app.Fragment) {
                        ((androidx.fragment.app.Fragment)instance).setArguments(postcard.getExtras());
                    }

                    return instance;
                } catch (Exception var10) {
                    logger.error("ARouter::", "Fetch fragment instance error, " + TextUtils.formatStackTrace(var10.getStackTrace()));
                }
            case METHOD:
            case SERVICE:
            default:
                return null;
        }
    }

附件:

ARouter完全解析:cloud.tencent.com/developer/a…

ARouter官方使用文档:github.com/alibaba/ARo…