Arouter之API原理解析

Arouter是什么及其注解处理器的原理在文章:Arouter之注解器处理器原理解析中有说明,建议先去看这篇文章,因为API原理解析依赖注解处理器生成的:路由表类文件、依赖注入辅助工具类文件、拦截器表类文件。

Arouter

Arouter类是Arouter框架的门面类,暴露接口给开发者调用,其所有方法都是调用_Arouter对应的方法。
我看下几个下几个常用的方法的源码:

public final class ARouter {
    private volatile static ARouter instance = null;
    
    public static void init(Application application) {
        //初始化Arouter,其内部调用的是_Arouter进行初始化
        if (!hasInit) {
            logger = _ARouter.logger;
            _ARouter.logger.info(Consts.TAG, "ARouter init start.");
            //调用的是_Arouter进行初始化
            hasInit = _ARouter.init(application);

            if (hasInit) {
               //初始化成功,调用_Arouter的afterInit方法
                _ARouter.afterInit();
            }

            _ARouter.logger.info(Consts.TAG, "ARouter init over.");
        }
    }

    public static ARouter getInstance() {
        //获取Arouter单例
        if (!hasInit) {
            //未初始化,则抛出异常
            throw new InitException("ARouter::Init::Invoke init(context) first!");
        } else {
            //已初始化,则创建Arouter单例
            if (instance == null) {
                synchronized (ARouter.class) {
                    if (instance == null) {
                        instance = new ARouter();
                    }
                }
            }
            return instance;
        }
    }

    public void inject(Object thiz) {
        //调用_ARouter的注入方法
        _ARouter.inject(thiz);
    }

    public Postcard build(String path) {
        //调用_ARouter单例通过路由路径构建路由明信片Postcard 
        return _ARouter.getInstance().build(path);
    }

    public Postcard build(Uri url) {
        //调用_ARouter单例通过路由url构建路由明信片Postcard 
        return _ARouter.getInstance().build(url);
    }

    public  T navigation(Class service) {
        //调用_ARouter单例通过服务Class导航到具体的服务,并返回服务对象
        return _ARouter.getInstance().navigation(service);
    }

    public Object navigation(Context mContext, Postcard postcard, int requestCode, NavigationCallback callback) {
         //调用_ARouter单例通过路由明信片导航到具体的路由,requestCode是startActivityForResult的requestCode
        return _ARouter.getInstance().navigation(mContext, postcard, requestCode, callback);
    }
}

根据Arouter的核心源码部分,我们得出如下结论:
1、使用Arouter之前,必须先进行初始化,否则会抛出未初始化的异常
2、Arouter的是作为_Arouter的门面,内部调用的是_Arouter对应的方法

Arouter初始化

Arouter的初始哈的真实实现是在_Arouter的init方法:

protected static synchronized boolean init(Application application) {
        mContext = application;
        LogisticsCenter.init(mContext, executor);
        logger.info(Consts.TAG, "ARouter init success!");
        hasInit = true;
        mHandler = new Handler(Looper.getMainLooper());

        return true;
    }

_Arouter的初始化接着调用LogisticsCenter的初始化方法:

public synchronized static void init(Context context, ThreadPoolExecutor tpe) throws HandlerException {
        mContext = context;
        executor = tpe;

        try {
            long startInit = System.currentTimeMillis();
            //load by plugin first
            loadRouterMap();
            if (registerByPlugin) {
                //如果使用了自动注册插件,则啥也不做
                logger.info(TAG, "Load router map by arouter-auto-register plugin.");
            } else {
                //如果没有使用自动注册插件,则需要完成RoutGroup、Provider、Interceptor的注册
                //路由文件集合(包括:RouteRoot、Provider、Interceptor),值为类全限定名
                Set routerMap;

                // It will rebuild router map every times when debuggable.
                if (ARouter.debuggable() || PackageUtils.isNewVersion(context)) {
                    //当前应用是新版本,重新从apk的dex中读取路由文件集合
                    logger.info(TAG, "Run with debug mode or new install, rebuild router map.");
                    // These class was generated by arouter-compiler.
                    //从apk的dex中读取所有的路由文件集合
                    routerMap = ClassUtils.getFileNameByPackageName(mContext, ROUTE_ROOT_PAKCAGE);
                    if (!routerMap.isEmpty()) {
                        //路由文件集合不为空,则将路由文件集合缓存到SharedPreferences中
                        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.");
                    routerMap = new HashSet<>(context.getSharedPreferences(AROUTER_SP_CACHE_KEY, Context.MODE_PRIVATE).getStringSet(AROUTER_SP_KEY_MAP, new HashSet()));
                }

                logger.info(TAG, "Find router map finished, map size = " + routerMap.size() + ", cost " + (System.currentTimeMillis() - startInit) + " ms.");
                startInit = System.currentTimeMillis();

                for (String className : routerMap) {
                    //遍历路由文件集合
                    if (className.startsWith(ROUTE_ROOT_PAKCAGE + DOT + SDK_NAME + SEPARATOR + SUFFIX_ROOT)) {
                        // This one of root elements, load root.
                        //如果路由文件类型为RouteRoot类型,反射创建RouteRoot对象,并调用其loadInto方法将路由组加载到全局路由组表Warehouse.groupsIndex中
                        ((IRouteRoot) (Class.forName(className).getConstructor().newInstance())).loadInto(Warehouse.groupsIndex);
                    } else if (className.startsWith(ROUTE_ROOT_PAKCAGE + DOT + SDK_NAME + SEPARATOR + SUFFIX_INTERCEPTORS)) {
                        //如果路由文件类型为Interceptor类型,反射创建Interceptor对象,并调用其loadInto方法将拦截器加载到全局拦截器表Warehouse.interceptorsIndex中
                        // Load interceptorMeta
                        ((IInterceptorGroup) (Class.forName(className).getConstructor().newInstance())).loadInto(Warehouse.interceptorsIndex);
                    } else if (className.startsWith(ROUTE_ROOT_PAKCAGE + DOT + SDK_NAME + SEPARATOR + SUFFIX_PROVIDERS)) {
                        // Load providerIndex
                        //如果路由文件类型为Provider类型,反射创建Provider对象,并调用其loadInto方法将provider加载到全局服务表Warehouse.providersIndex中
                        ((IProviderGroup) (Class.forName(className).getConstructor().newInstance())).loadInto(Warehouse.providersIndex);
                    }
                }
            }
           //.....
        } catch (Exception e) {
          //.....
        }
    }

根据上述源码的解析,我们可以得出以下结论:
1、Arouter的初始化最终进入LogisticsCenter的init方法实现初始化
2、初始化的工作主要是:

  • 设置全局context
  • 如果没有使用自动注册插件,那么就是将注解器生成的路由组RouteRoot文件、拦截器文件InterceptorGroup、服务Provider注册到全局变量中,全局变量分别是:
    • Warehouse.groupsIndex:路由组表,key是组名,value是路由组RouteGroup的Class
    • Warehouse.interceptorsIndex:拦截器列表,key是拦截器优先级,value是拦截器InterceptorGroup的class
    • Warehouse.providersIndex:服务表,key是服务器类全限定名,value是描述服务的路由元RouteMeta对象

Arouter导航

Arouter的导航可以实现:打开指定路由的Activity、获取指定路由的Fragment/ContentProvider/Boardcast、获取指定路由的Provider。导航的方式分为

  • 根据路由路径path进行导航
  • 根据uri进行导航
  • 根据服务的class进行导航
路径导航

我们先看通过路径进行导航的源码流程:
Arouter的build(path)和build(path, group)都会进入_Arouter对应的方法,我们直接看_Arouter对应的方法:

protected Postcard build(String path) {
        if (TextUtils.isEmpty(path)) {
            throw new HandlerException(Consts.TAG + "Parameter is invalid!");
        } else {
            //这一步主要主要是路由重定向,就是把path转换为其它的路由路径
            PathReplaceService pService = ARouter.getInstance().navigation(PathReplaceService.class);
            if (null != pService) {
                path = pService.forString(path);
            }
            //第二个参数extractGroup取paht的第一段//作为组名
            //第三个参数表示是经过重定向的
            return build(path, extractGroup(path), true);
        }
    }
protected Postcard build(String path, String group, Boolean afterReplace) {
        //构建路由明信片Postcard 
        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);
                }
            }
            //通过路由路径和组名创建路由明信片Postcard
            return new Postcard(path, group);
        }
    }

构建出路由明信片Postcard之后,调用Postcard的导航方法navigation继续完成导航:

public Object navigation(Context context) {
        return navigation(context, null);
    }
public Object navigation(Context context, NavigationCallback callback) {
        return ARouter.getInstance().navigation(context, this, -1, callback);
    }
public void navigation(Activity mContext, int requestCode) {
        navigation(mContext, requestCode, null);
    }
public void navigation(Activity mContext, int requestCode, NavigationCallback callback) {
        ARouter.getInstance().navigation(mContext, this, requestCode, callback);
    }

最终调用_Arouter的navigation(mContext, postcard, requestCode, callback)方法:

protected Object navigation(final Context context, final Postcard postcard, final int requestCode, final NavigationCallback callback) {
        //导航前逻辑
        PretreatmentService pretreatmentService = ARouter.getInstance().navigation(PretreatmentService.class);
        if (null != pretreatmentService && !pretreatmentService.onPretreatment(context, postcard)) {
            // Pretreatment failed, navigation canceled.
          //导航前终止了继续导航
            return null;
        }

        // Set context to postcard.
        //明信片设置上下文context
        postcard.setContext(null == context ? mContext : context);

        try {
            //构建路由明信片的完整信息,如路由具体信息、路由需要依赖注入的参数等
            LogisticsCenter.completion(postcard);
        } catch (NoRouteFoundException ex) {
           //......
           //导航失败
            if (null != callback) {
                //回调导航失败
                callback.onLost(postcard);
            } else {
                // No callback for this invoke, then we use the global degrade service.
                //获取降级处理器
                DegradeService degradeService = ARouter.getInstance().navigation(DegradeService.class);
                if (null != degradeService) {
                    //进行降级处理
                    degradeService.onLost(context, postcard);
                }
            }

            return null;
        }

        if (null != callback) {
            //回调找到了目标路由
            callback.onFound(postcard);
        }

        if (!postcard.isGreenChannel()) {   // It must be run in async thread, maybe interceptor cost too mush time made ANR.
            //如果路由非绿色通道
            //调用拦截器调度中心,开始递归调用拦截器进行处理拦截逻辑
            interceptorService.doInterceptions(postcard, new InterceptorCallback() {
                /**
                 * Continue process
                 *
                 * @param postcard route meta
                 */
                @Override
                public void onContinue(Postcard postcard) {
                    //没有拦截器拦截当前路由,则调用_navigation继续完成路由导航
                    _navigation(postcard, requestCode, callback);
                }

                /**
                 * Interrupt process, pipeline will be destory when this method called.
                 *
                 * @param exception Reson of interrupt.
                 */
                @Override
                public void onInterrupt(Throwable exception) {
                    //当前路由被拦截器拦截,回调告知被拦截器拦截了
                    if (null != callback) {
                        callback.onInterrupt(postcard);
                    }

                    logger.info(Consts.TAG, "Navigation failed, termination by interceptor : " + exception.getMessage());
                }
            });
        } else {
            //绿色通道,直接调用_navigation继续完成路由导航
            return _navigation(postcard, requestCode, callback);
        }

        return null;
    }

我们先看LogisticsCenter怎么完善明信片的信息:

public synchronized static void completion(Postcard postcard) {
       //.....
        //根据路由路径,从路由表中获取路由信息
        RouteMeta routeMeta = Warehouse.routes.get(postcard.getPath());
        if (null == routeMeta) {
            //未加载路由
            // Maybe its does't exist, or didn't load.
            if (!Warehouse.groupsIndex.containsKey(postcard.getGroup())) {
                //如果路由组中没有匹配的路由,则抛出异常
                throw new NoRouteFoundException(TAG + "There is no route match the path [" + postcard.getPath() + "], in group [" + postcard.getGroup() + "]");
            } else {
                // Load route and cache it into memory, then delete from metas.
                try {
                   //......
                    //动态的将路由组中路由都加载到路由表中
                    addRouteGroupDynamic(postcard.getGroup(), null);

                   //......
                } catch (Exception e) {
                    throw new HandlerException(TAG + "Fatal exception when loading group meta. [" + e.getMessage() + "]");
                }
                //加载完路由,重新调用completion完善路由明信片
                completion(postcard);   // Reload
            }
        } else {
            //已加载路由
            //设置路由class
            postcard.setDestination(routeMeta.getDestination());
            //设置路由类型
            postcard.setType(routeMeta.getType());
            //设置路由优先级
            postcard.setPriority(routeMeta.getPriority());
            //设置路由附加信息
            postcard.setExtra(routeMeta.getExtra());
            
            Uri rawUri = postcard.getUri();
            if (null != rawUri) {   // Try to set params into bundle.
                //如果通过Uri导航,则将uri中的query转为bundle参数值列表
                Map resultMap = TextUtils.splitQueryParameters(rawUri);
                //路由需要依赖注入的参数类型列表
                Map paramsType = routeMeta.getParamsType();

                if (MapUtils.isNotEmpty(paramsType)) {
                    // Set value by its type, just for params which annotation by @Param
                    //根据需要依赖注入的参数类型列表构建出传递给路由的参数值Bundle
                    for (Map.Entry params : paramsType.entrySet()) {
                        setValue(postcard,
                                params.getValue(),
                                params.getKey(),
                                resultMap.get(params.getKey()));
                    }

                    // Save params name which need auto inject.
                    //将需要依赖注入的字段列表传递给路由参数,待后面完成依赖注入
                    postcard.getExtras().putStringArray(ARouter.AUTO_INJECT, paramsType.keySet().toArray(new String[]{}));
                }

                // Save raw uri
                //将uri也作为参数值也传给路由
                postcard.withString(ARouter.RAW_URI, rawUri.toString());
            }

            switch (routeMeta.getType()) {
                case PROVIDER:  // if the route is provider, should find its instance
                    // Its provider, so it must implement IProvider
                    //如果路由类型是Provider类型,则:
                    //反射创建服务实现类,并放入全局服务表Warehouse.providers中
                    Class providerMeta = (Class) routeMeta.getDestination();
                    IProvider instance = Warehouse.providers.get(providerMeta);
                    
                    if (null == instance) { // There's no instance of this provider
                        //如果服务未创建
                        IProvider provider;
                        try {
                            //反射创建服务,并缓存在全局服务表
                            provider = providerMeta.getConstructor().newInstance();
                            //初始化provider
                            provider.init(mContext);
                            //将provider放入全球服务表Warehouse.providers中
                            Warehouse.providers.put(providerMeta, provider);
                            instance = provider;
                        } catch (Exception e) {
                            logger.error(TAG, "Init provider failed!", e);
                            throw new HandlerException("Init provider failed!");
                        }
                    }
                    //设置路由明信片的服务提供者
                    postcard.setProvider(instance);
                    //所有的provider都不需要拦截,直接设置为绿色通道
                    postcard.greenChannel();    // Provider should skip all of interceptors
                    break;
                case FRAGMENT:
                    //所有的fragment不需要拦截,直接设置为绿色通道
                    postcard.greenChannel();    // Fragment needn't interceptors
                default:
                    break;
            }
        }
    }

public synchronized static void addRouteGroupDynamic(String groupName, IRouteGroup group) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        //动态加载路由组,将路由组内的路由加入全局路由表Warehouse.routes中
        if (Warehouse.groupsIndex.containsKey(groupName)){\
           //如果存在路由组RouteGroup,则:
            // If this group is included, but it has not been loaded
            // load this group first, because dynamic route has high priority.
            //从全局路由组表Warehouse.groupsIndex中获取路由组的class,通过反射创建路由组对象,并调用loadInto方法将组内的路由将入全局路由表Warehouse.routes中
Warehouse.groupsIndex.get(groupName).getConstructor().newInstance().loadInto(Warehouse.routes);
            Warehouse.groupsIndex.remove(groupName);
        }

        // cover old group.
        if (null != group) {
            group.loadInto(Warehouse.routes);
        }
    }

LogisticsCenter的completion是通过从全局路由组表反射Warehouse.groupsIndex中的路由组RouteGroup对象,并调用RouteGroup对象的loadInto将组内路由加入全局路由表Warehouse.routes,接着从路由表中获取路由元对象RouteMeta的信息来填充完善路由明信片postcard对象,包括目标路由的class、目标路由需要注入的参数列表及其参数值、目标provider等。
我们接着来分析上面导航时没有被拦截,需要继续完成导航的_Arouter的_navigation的源码:

private Object _navigation(final Postcard postcard, final int requestCode, final NavigationCallback callback) {
        //获取上下文context:activity或者applicationcontext
        final Context currentContext = postcard.getContext();

        switch (postcard.getType()) {
            case ACTIVITY:
                // Build intent
                //如果目标路由是activity,则:
                //创建activity的意图intent,class是路由名片中目标路由activity的class
                final Intent intent = new Intent(currentContext, postcard.getDestination());
                //设置意图的参数,即需要依赖注入的字段列表及其参数值
                intent.putExtras(postcard.getExtras());

                // Set flags.
                //设置意图标志位
                int flags = postcard.getFlags();
                if (0 != flags) {
                    intent.setFlags(flags);
                }

                // Non activity, need FLAG_ACTIVITY_NEW_TASK
                if (!(currentContext instanceof Activity)) {
                    //如果上下文不是activity,则需要在新的栈中打开activity
                    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                }

                // Set Actions
                //设置intent的action
                String action = postcard.getAction();
                if (!TextUtils.isEmpty(action)) {
                    intent.setAction(action);
                }
              
                // Navigation in main looper.
                runInMainThread(new Runnable() {
                    @Override
                    public void run() {
                        //回到主线程打开activity
                        startActivity(requestCode, currentContext, intent, postcard, callback);
                    }
                });

                break;
            case PROVIDER:
                //如果目标路由是provider类型,则:
                //直接返回目标路由提供的服务对象
                return postcard.getProvider();
            case BOARDCAST:
            case CONTENT_PROVIDER:
            case FRAGMENT:
                //如果目标路由是fragment/contentProvider/Boardcast,则:
                //获取目标路由的class
                Class fragmentMeta = postcard.getDestination();
                try {
                     //通过class反射目标路由对象
                    Object instance = fragmentMeta.getConstructor().newInstance();
                    if (instance instanceof Fragment) {
                         //如果是fragment,则设置参数及其参数值
                        ((Fragment) instance).setArguments(postcard.getExtras());
                    } else if (instance instanceof android.support.v4.app.Fragment) {
                        //如果是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;
    }

到此完成整改路由导航的流程。

Uri导航

我们接着看通过uri导航的源码流程:
Arouter的build(Uri uri)会进入_Arouter对应的方法,我们直接看_Arouter对应的方法:

protected Postcard build(Uri uri) {
        if (null == uri || TextUtils.isEmpty(uri.toString())) {
            //无效的uri抛出异常
            throw new HandlerException(Consts.TAG + "Parameter invalid!");
        } else {
            //路由重定向
            PathReplaceService pService = ARouter.getInstance().navigation(PathReplaceService.class);
            if (null != pService) {
                uri = pService.forUri(uri);
            }
            //从uri中取出路由路径path,使用路由路径的第一段//中的字符串作为路由组名,使用path和组名创建路由明信片
            return new Postcard(uri.getPath(), extractGroup(uri.getPath()), uri, null);
        }
    }

uri导航的方式是从uri中路由路径path,使用路由路径的第一段//中的字符串作为路由组名,使用path和组名创建路由明信片。创建出路由明信片之后,接下来的导航流程与上面分析的“路径导航”一样,在此不做重复介绍。

Class导航

我们接着看通过Class导航的流程,class导航方式只能导航到模块提供的服务,且会返回class对应的服务对象,直接使用的是navigation方法,我们来看看navigation(Class service)的源码流程:

protected  T navigation(Class service) {
        try {
            //通过服务类的全限定名构建路由明信片
            Postcard postcard = LogisticsCenter.buildProvider(service.getName());

            // Compatible 1.0.5 compiler sdk.
            // Earlier versions did not use the fully qualified name to get the service
            if (null == postcard) {
                //如果找不到路由,则
                // No service, or this service in old version.
                //使用服务类的简单类名(不含包名)来构建路由明信片
                postcard = LogisticsCenter.buildProvider(service.getSimpleName());
            }

            if (null == postcard) {
                //如果找不到路由,则返回空
                return null;
            }

            // Set application to postcard.
            //找到路由,设置路由明信片的上下文
            postcard.setContext(mContext);
            //完善路由明信片
            LogisticsCenter.completion(postcard);
            //直接返回路由明信片中的服务对象
            return (T) postcard.getProvider();
        } catch (NoRouteFoundException ex) {
            logger.warning(Consts.TAG, ex.getMessage());
            return null;
        }
    }


//LogisticsCenter.buildProvider
public static Postcard buildProvider(String serviceName) {
        //根据服务类名从全局服务表Warehouse.providersIndex中取出服务对应的路由元信息对象meta 
        RouteMeta meta = Warehouse.providersIndex.get(serviceName);

        if (null == meta) {
            //找不到服务,返回空
            return null;
        } else {
            //找到服务,则通过路由元信息中的路由路径和组名创建路由明信片并返回
            return new Postcard(meta.getPath(), meta.getGroup());
        }
    }

通过class进行导航是为获取模块提供的服务服务的,它先根据服务类名从全局服务表Warehouse.providersIndex中取出服务对应的路由元信息对象,使用此路由元信息创建对应的路由明信片对象,接着调用LogisticsCenter.completion完善路由明信片,完善的逻辑在上面的“路由导航”有分析过,在此不做重复介绍,接着返回明信片中的服务对象,完成本次导航。

导航拦截

在上面的路由导航分析中,在导航时有介绍到使用了拦截器对导航进行拦截处理,我们来看看拦截器的工作原理:
首先呢,Arouter的Api中内置了一个拦截处理中心InterceptorServiceImpl,它是一个服务提供者,提供的是为导航调度所有拦截器的逻辑,我们来看看其源码:

@Route(path = "/arouter/service/interceptor")
public class InterceptorServiceImpl implements InterceptorService {
    //拦截器调度中心类
   //是否已初始化
    private static boolean interceptorHasInit;
   //初始化锁对象
    private static final Object interceptorInitLock = new Object();

    @Override
    public void doInterceptions(final Postcard postcard, final InterceptorCallback callback) {
        //开始调度拦截器
        if (MapUtils.isNotEmpty(Warehouse.interceptorsIndex)) {
            //如果拦截表不为空,则:
            //等待拦截器调度中心完成初始化
            checkInterceptorsInitStatus();

            if (!interceptorHasInit) {
                 //未初始化,回调告知拦截器初始化太耗时
                callback.onInterrupt(new HandlerException("Interceptors initialization takes too much time."));
                return;
            }

            LogisticsCenter.executor.execute(new Runnable() {
                @Override
                public void run() {
                    CancelableCountDownLatch interceptorCounter = new CancelableCountDownLatch(Warehouse.interceptors.size());
                    try {
                        //根据优先级依次调用拦截器的处理程序
                        _execute(0, interceptorCounter, postcard);
                        interceptorCounter.await(postcard.getTimeout(), TimeUnit.SECONDS);
                        if (interceptorCounter.getCount() > 0) {    // Cancel the navigation this time, if it hasn't return anythings.
                             //回调告知已被拦截
                            callback.onInterrupt(new HandlerException("The interceptor processing timed out."));
                        } else if (null != postcard.getTag()) {    // Maybe some exception in the tag.
                            //回调告知已被拦截
                            callback.onInterrupt((Throwable) postcard.getTag());
                        } else {
                           //回调告知没有被拦截
                            callback.onContinue(postcard);
                        }
                    } catch (Exception e) {
                        //回调告知已被拦截
                        callback.onInterrupt(e);
                    }
                }
            });
        } else {
            //没有拦截器
            //回调告知没有被拦截
            callback.onContinue(postcard);
        }
    }

    /**
     * Excute interceptor
     *
     * @param index    current interceptor index
     * @param counter  interceptor counter
     * @param postcard routeMeta
     */
    private static void _execute(final int index, final CancelableCountDownLatch counter, final Postcard postcard) {
        if (index < Warehouse.interceptors.size()) {
            //根据索引从全局拦截器表中获取拦截器
            IInterceptor iInterceptor = Warehouse.interceptors.get(index);
            //调用拦截器的处理程序
            iInterceptor.process(postcard, new InterceptorCallback() {
                @Override
                public void onContinue(Postcard postcard) {
                    // Last interceptor excute over with no exception.
                    //如果拦截器不拦截,则交给下一个拦截器处理
                    counter.countDown();
                    _execute(index + 1, counter, postcard);  // When counter is down, it will be execute continue ,but index bigger than interceptors size, then U know.
                }

                @Override
                public void onInterrupt(Throwable exception) {
                    // Last interceptor execute over with fatal exception.
                    //被拦截器拦截,并结束拦截流程
                    postcard.setTag(null == exception ? new HandlerException("No message.") : exception);    // save the exception message for backup.
                    counter.cancel();
                    // Be attention, maybe the thread in callback has been changed,
                    // then the catch block(L207) will be invalid.
                    // The worst is the thread changed to main thread, then the app will be crash, if you throw this exception!
//                    if (!Looper.getMainLooper().equals(Looper.myLooper())) {    // You shouldn't throw the exception if the thread is main thread.
//                        throw new HandlerException(exception.getMessage());
//                    }
                }
            });
        }
    }

    @Override
    public void init(final Context context) {
        //初始化拦截器调度中心服务,是在_Arouter的afterinit中最终调用LogisticsCenter.completion调用的
        LogisticsCenter.executor.execute(new Runnable() {
            @Override
            public void run() {
                if (MapUtils.isNotEmpty(Warehouse.interceptorsIndex)) {
                  
                    for (Map.Entry> entry : Warehouse.interceptorsIndex.entrySet()) {
                        //遍历拦截器class列表
                        Class interceptorClass = entry.getValue();
                        try {
                            //根据class反射创建拦截器
                            IInterceptor iInterceptor = interceptorClass.getConstructor().newInstance();
                            //初始拦截器
                            iInterceptor.init(context);
                            //将拦截器加入
                            Warehouse.interceptors.add(iInterceptor);
                        } catch (Exception ex) {
                            throw new HandlerException(TAG + "ARouter init interceptor error! name = [" + interceptorClass.getName() + "], reason = [" + ex.getMessage() + "]");
                        }
                    }
                    //标记拦截器调度中心已初始哈
                    interceptorHasInit = true;

                    logger.info(TAG, "ARouter interceptors init over.");

                    synchronized (interceptorInitLock) {
                        //唤醒等待拦截器调度中心初始化锁
                        interceptorInitLock.notifyAll();
                    }
                }
            }
        });
    }

    private static void checkInterceptorsInitStatus() {
      //检测拦截器
        synchronized (interceptorInitLock) {
            while (!interceptorHasInit) {
                try {
                    //等待拦截器调度中心完成初始化
                    interceptorInitLock.wait(10 * 1000);
                } catch (InterruptedException e) {
                    throw new HandlerException(TAG + "Interceptor init cost too much time error! reason = [" + e.getMessage() + "]");
                }
            }
        }
    }
}

Arouter依赖注入

我们接着分析依赖注入的源码流程:

static void inject(Object thiz) {
        //获取Arouter内置的依赖注入服务类
        AutowiredService autowiredService = ((AutowiredService) ARouter.getInstance().build("/arouter/service/autowired").navigation());
        if (null != autowiredService) {
            //调用autowire实现自动注入
            autowiredService.autowire(thiz);
        }
    }

Arouter内置了依赖注入服务类AutowiredServiceImpl,我们接着来分析AutowiredServiceImpl:

@Route(path = "/arouter/service/autowired")
public class AutowiredServiceImpl implements AutowiredService {
    //lrucache:最近最少使用的依赖注入类
    private LruCache classCache;
    //黑名单列表
    private List blackList;

    @Override
    public void init(Context context) {
        //设置最近最少使用LruCache最大容量为50,即最大缓存50个依赖注入类
        classCache = new LruCache<>(50);
        blackList = new ArrayList<>();
    }

    @Override
    public void autowire(Object instance) {
        //主动注入
        //调用doInject完成自动注入
        doInject(instance, null);
    }

    /**
     * Recursive injection
     *
     * @param instance who call me.
     * @param parent   parent of me.
     */
    private void doInject(Object instance, Class parent) {
        //parant是需要注入的类
        Class clazz = null == parent ? instance.getClass() : parent;
        
        //根据类名获取注射器
        ISyringe syringe = getSyringe(clazz);
        if (null != syringe) {
            //如果注射器不为空,则调用注射器的inject方法,完成对目标类instance中需要依赖注入的字段进行注入赋值
            syringe.inject(instance);
        }
        //获取目标类的父类
        Class superClazz = clazz.getSuperclass();
        // has parent and its not the class of framework.
        if (null != superClazz && !superClazz.getName().startsWith("android")) {
            //继续对目标类的父类完成依赖注入
            doInject(instance, superClazz);
        }
    }

    private ISyringe getSyringe(Class clazz) {
        String className = clazz.getName();

        try {
            if (!blackList.contains(className)) {
                //黑名单不含此注射器,则:
                //从缓存区注射器
                ISyringe syringeHelper = classCache.get(className);
                if (null == syringeHelper) {  // No cache.
                    //如果缓存中不存在注册器,则:
                    //通过类名反射创建注射器对象
                    syringeHelper = (ISyringe) Class.forName(clazz.getName() + SUFFIX_AUTOWIRED).getConstructor().newInstance();
                }
                //将注射器将入缓存中
                classCache.put(className, syringeHelper);
                //返回注射器
                return syringeHelper;
            }
        } catch (Exception e) {
            //获取注射器异常,则加入黑名单
            blackList.add(className);    // This instance need not autowired.
        }

        return null;
    }
}

结合上述源码的分析,我们对Arouter可以做如下概括:
1、对Arouter初始化时,如果没有使用自动注册插件,则需要执行以下的注册操作:

  • 从apk的dex文件中找出所有的路由组文件RouteRoot、服务类文件Provider、拦截器文件
  • 反射创建这些类,并调用他们的loadInto方法:将路由组放入全局路由组表Warehouse.groupsIndex中、将拦截器放入全局拦截器索引表中、Warehouse.interceptorsIndex中、将服务路由信息放入全局服务索引表Warehouse.providersIndex中。

2、初始化完成后,导航到拦截器调度中心服务,并完成拦截器调度中心服务的初始化
3、导航时根据路由路径、路由组生成路由明信片对象,接着调用LogisticsCenter的completion完善路由明信片的信息:

  • 反射创建路由组对象RouteRoot,调用RouteRoot的loadInto方法,将组内的路由都缓存到全局的路由表Warehouse.routes中
  • 从全局路由表Warehouse.routes中获取路由元信息,并设置路由明信片的目标路由class、需要注入的字段列表及其参数值、如果是服务则设置服务并进行初始化

4、非绿色通道需要调用拦截器调度中心,调度所有的拦截器进行处理,如果不拦截则最终调用最后的导航步骤6
5、绿色通道直接进入最终的导航步骤6
6、最后的导航步骤

  • 如果是activity,使用明信片的信息构建目标activity的intent、参数列表、标志位等。进入目标activity之后,如果需要依赖注入,则调用inject方法调用对应的注入辅助类完成对字段的注入赋值
  • 如果是fragment,反射创建fragment,并使用明信片的信息设置参数列表,并返回fragment。进入目标fragment之后,如果需要依赖注入,则调用inject方法调用对应的注入辅助类完成对字段的注入赋值
  • 如果是provider,直接返回明信片中的provider
  • 如果是contentprovider或者boardcast,反射创建contentprovider或者boardcast,然后返回contentprovider或者boardcast

你可能感兴趣的:(Arouter之API原理解析)