ARouter源码再分析

一、概述

  ARouter是一个路由框架,主要解决平行模块之间页面跳转的问题。

  ARouter基本原理---->ps:简化版:

    1.其核心还是通过Intent进行跳转

    2.通过注解+APT+JavaPoet技术,把项目中包含有@Router(path)注解的类找出来,然后把含有注解@Rotue的类和路由路径path一一映射。然后保存在Map中。

    3.通过ARouter.getInstance().build(path).navigation()做页面跳转,根据路由path找到对应的Activity,并通过intent进行跳转

    

    ps:下面就来看看简化版的源码分析

二、源码分析

  源码分析主要看以下几个方法:

    1.ARouter.init(applicationContex)//初始化

    2.ARouter.getInstance.build(路由path).navigation()//跳转

  一、初始化init方法的调用关系

    ARouter的init方法啥也没做,只是调用了_ARouter.init()方法,而_ARouter.init方法中又调用了LogisticsCenter.init方法,然后使用其init方法把包含@Router的类映射到Warsehouse中。其主要的代码就在这里

ARouter.init()方法
public
static void init(Application application) { if (!hasInit) { ......省略
        //等于说啥也没做,就是包装了一下
hasInit = _ARouter.init(application);         ....省略 } }
_ARouter.init方法
protected static synchronized boolean init(Application application) { mContext = application; LogisticsCenter.init(mContext, executor);//交给LogisticsCenter去初始化 logger.info(Consts.TAG, "ARouter init success!"); hasInit = true; mHandler = new Handler(Looper.getMainLooper());//创建了一个MainHandler return true; }
LogisticsCenter.init方法
public synchronized static void init(Context context, ThreadPoolExecutor tpe) throws HandlerException { mContext = context; executor = tpe; try {   .... loadRouterMap(); if (registerByPlugin) {//检查插件 logger.info(TAG, "Load router map by arouter-auto-register plugin."); } else { Set<String> routerMap; // It will rebuild router map every times when debuggable. if (ARouter.debuggable() || PackageUtils.isNewVersion(context)) { logger.info(TAG, "Run with debug mode or new install, rebuild router map."); // These class was generated by arouter-compiler. routerMap = ClassUtils.getFileNameByPackageName(mContext, ROUTE_ROOT_PAKCAGE);//从包中加载类路径存入集合,包中的类是通过APT+JavaPoet提前生成的 if (!routerMap.isEmpty()) { context.getSharedPreferences(AROUTER_SP_CACHE_KEY, Context.MODE_PRIVATE).edit().putStringSet(AROUTER_SP_KEY_MAP, routerMap).apply(); } PackageUtils.updateVersion(context); // Save new version name when router map update finishes. } else { logger.info(TAG, "Load router map from cache.");
            //在缓存中加载含有@Router注解的类路径 routerMap
= new HashSet<>(context.getSharedPreferences(AROUTER_SP_CACHE_KEY, Context.MODE_PRIVATE).getStringSet(AROUTER_SP_KEY_MAP, new HashSet<String>())); }           ........ for (String className : routerMap) { if (className.startsWith(ROUTE_ROOT_PAKCAGE + DOT + SDK_NAME + SEPARATOR + SUFFIX_ROOT)) { // This one of root elements, load root.实例化@Router标注的类后一个个的加入到Warehouse.groupsIndex(ps:其是一个map,在执行navigation的时候会用到这个东西) ((IRouteRoot) (Class.forName(className).getConstructor().newInstance())).loadInto(Warehouse.groupsIndex); } else if (className.startsWith(ROUTE_ROOT_PAKCAGE + DOT + SDK_NAME + SEPARATOR + SUFFIX_INTERCEPTORS)) { ....... } } }       ....... }

  二、执行build.(path).navigation()跳转

  1.build(path)方法最主要的的目的是生成一个Postcard对象,并把path复制给Postcard对象。而这个对象的主要作用就是存储跳转信息。

protected Postcard build(String path, String group, Boolean afterReplace) {
        if (TextUtils.isEmpty(path) || TextUtils.isEmpty(group)) {
            throw new HandlerException(Consts.TAG + "Parameter is invalid!");
        } else {
            if (!afterReplace) {
                PathReplaceService pService = ARouter.getInstance().navigation(PathReplaceService.class);
                if (null != pService) {
                    path = pService.forString(path);
                }
            }
            return new Postcard(path, group);//最终的目的,就是为了生成Postcard对象,
        }
    }

  2.navigation()方法最主要的作用就是利用Postcard对象中的信息做跳转

protected Object navigation(final Context context, final Postcard postcard, final int requestCode, final NavigationCallback callback) {
        PretreatmentService pretreatmentService = ARouter.getInstance().navigation(PretreatmentService.class);
          ....省略
            LogisticsCenter.completion(postcard);
          ....省略

          ....省略return _navigation(context, postcard, requestCode, callback);
          ....省略

        return null;
    }

  以上就是_ARouter中的navigation方法,里面有来个重要的方法,分别是:LogisticsCenter.completion(postcard)、_navigation()

  LogisticsCenter.completion()方法主要是用来获取路由信息,并把路由信息存入postcard中。

public synchronized static void completion(Postcard postcard) {
        ...
        RouteMeta routeMeta = Warehouse.routes.get(postcard.getPath());//根据路由路径获取路由对象
         .....
        //设置路由参数
postcard.setDestination(routeMeta.getDestination()); postcard.setType(routeMeta.getType()); postcard.setPriority(routeMeta.getPriority()); postcard.setExtra(routeMeta.getExtra());   ...... }

  _navigation()方法中实现真正的跳转

private Object _navigation(final Context context, final Postcard postcard, final int requestCode, final NavigationCallback callback) {
        final Context currentContext = null == context ? mContext : context;

        switch (postcard.getType()) {//跳转类型,四大组件外加一个Fragment
            case ACTIVITY:
                // Build intent
                final Intent intent = new Intent(currentContext, postcard.getDestination());//从postcard中获取跳转信息
                intent.putExtras(postcard.getExtras());//设置跳转参数

                // Set flags.
                int flags = postcard.getFlags();
                if (-1 != flags) {
                    intent.setFlags(flags);
                } else if (!(currentContext instanceof Activity)) {    // Non activity, need less one flag.
                    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);//启动一个新的activity
                }
          ......
                // Navigation in main looper.
                runInMainThread(new Runnable() {
                    @Override
                    public void run() {
                        startActivity(requestCode, currentContext, intent, postcard, callback);//在主线程中执行跳转动作
                    }
                });

                ......return null;
    }

  到此分析算是完,大概得意思就是ARouter是一个路由框架。原理是:通过APT找到@Router(path)注解标注的类,并于注解上的path做映射.存入HashMap中并加载到内存。ARouter通过build(path).navigation()跳转的时候通过path从HashMap中取出路由信息,封装Intent后进行跳转。

posted on 2023-08-22 16:19  飘杨......  阅读(15)  评论(0编辑  收藏  举报