ARouter源码解析04-interceptor拦截器
来源:互联网 发布:网络it外包 编辑:程序博客网 时间:2024/05/21 09:28
上篇文章我们分析了ARouter的路由跳转,这篇文章我们来分析interceptor拦截器。
首先,同样在IDE编译过程中,拦截器也会产生相应的文件。(详见ARouter源码解析01-编译生成文件)
public class ARouter$$Interceptors$$app implements IInterceptorGroup { @Override public void loadInto(Map<Integer, Class<? extends IInterceptor>> interceptors) { interceptors.put(3, Test2Interceptor.class); interceptors.put(5, Test3Interceptor.class); interceptors.put(7, Test1Interceptor.class); }}
可以看到,这里根据priority将Intercepter按照级别进行排序,级别从高到第依次put到interceptors集合中。那么,这些intercepter是在什么地方加载到内存中的呢?
同时,我们知道,拦截器有个init()方法,会在程序初始化的时候,进行调用,那么,是在哪里执行拦截器的init()方法的呢?
再回到ARouter.init()来看
public static void init(Application application) {//...hasInit = _ARouter.init(application);if (hasInit) { _ARouter.afterInit();}//...
}
这里有个afterInit方法,我们跟进去看下
static void afterInit() { // Trigger interceptor init, use byName. interceptorService = (InterceptorService) ARouter.getInstance().build("/arouter/service/interceptor").navigation();}
这里,通过路由跳转,调用了InterceptorServiceImpl,但是在路由app模块build文件中,并没有/arouter/service/interceptor这个路由表单,那么ARouter这里是通过怎么跳转的呢?
原来,在aroute-api中,还有个arouter的build文件,在这个文件下,有着和app模块下build包名相同的ARouter开头的几个文件(故ARouter.init的时候,也会把这几个路由表单加载进去)
package com.alibaba.android.arouter.routes;public class ARouter$$Group$$arouter implements IRouteGroup { @Override public void loadInto(Map<String, RouteMeta> atlas) { atlas.put("/arouter/service/autowired", RouteMeta.build(RouteType.PROVIDER, AutowiredServiceImpl.class, "/arouter/service/autowired", "arouter", null, -1, -2147483648)); atlas.put("/arouter/service/interceptor", RouteMeta.build(RouteType.PROVIDER, InterceptorServiceImpl.class, "/arouter/service/interceptor", "arouter", null, -1, -2147483648)); }}
我们再来在InterceptorServiceImpl,首先会在navigation的时候调用 LogisticsCenter.completion从而调用provider.init()方法进行初始化。
@Overridepublic void init(final Context context) { LogisticsCenter.executor.execute(new Runnable() { @Override public void run() { if (MapUtils.isNotEmpty(Warehouse.interceptorsIndex)) { for (Map.Entry<Integer, Class<? extends IInterceptor>> entry : Warehouse.interceptorsIndex.entrySet()) { Class<? extends IInterceptor> interceptorClass = entry.getValue(); try { 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; synchronized (interceptorInitLock) { interceptorInitLock.notifyAll(); } } } });}
可以发现,大体的,就是通过线程池.execute(),在异步线程中,获取所有的拦截器IInterceptor,调用他们的init方法,并把拦截器添加到Warehouse.interceptors集合中。
知道了
接着,继续在navigation方法中,如果没有把postcard.isGreenChannel设为true,那么调用interceptorService.doInterceptions执行拦截器,处理是否拦截。
完成了拦截器的init(),再来看navigation的时候,拦截器的拦截,
final class _ARouter { protected Object navigation(final Context context, final Postcard postcard, final int requestCode, final NavigationCallback callback) { LogisticsCenter.completion(postcard); //isGreenChannel為ture,說明不需要interceptor,要跳過interceptor if (!postcard.isGreenChannel()) { interceptorService.doInterceptions(postcard, new InterceptorCallback() { @Override public void onContinue(Postcard postcard) { _navigation(context, postcard, requestCode, callback); } @Override public void onInterrupt(Throwable exception) { if (null != callback) { callback.onInterrupt(postcard); } } }); } else { return _navigation(context, postcard, requestCode, callback); } return null; }}
来看doInterceptions(),这里进行拦截器的拦截,会遍历拦截器列表,并调用拦截器的process(),最终,根据结果回调onContinue或onInterrupt来继续navigation或终止navigation。
@Overridepublic void doInterceptions(final Postcard postcard, final InterceptorCallback callback) { // 检查拦截器列表是否为空 if (CollectionUtils.isNotEmpty(Warehouse.interceptors)) { // 等待拦截器服务完成初始化 // ...... LogisticsCenter.executor.execute(new Runnable() { @Override public void run() { // CountDown倒数计数器 CancelableCountDownLatch interceptorCounter = new CancelableCountDownLatch(Warehouse.interceptors.size()); try { // 在另一个线程中递归依次执行拦截器操作 _excute(0, interceptorCounter, postcard); // 等待超时 interceptorCounter.await(postcard.getTimeout(), TimeUnit.SECONDS); // 倒数计时器不为0,表示还有拦截器未执行完成 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(new HandlerException(postcard.getTag().toString())); } 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 _excute(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(); _excute(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 excute over with fatal exception. postcard.setTag(null == exception ? new HandlerException("No message.") : exception.getMessage()); // save the exception message for backup. counter.cancel(); } }); }}
至此,即完成了interceptor的拦截,下篇文章,我们来解析ARouter的自动注入参数的功能。
- ARouter源码解析04-interceptor拦截器
- OkHttp 源码解析(3) Interceptor 拦截器
- Okhttp源码解析之Interceptor(拦截器)
- OkHttp 3.x 源码解析之Interceptor 拦截器
- ARouter 拦截器与路由的实现(源码分析)
- ARouter源码解析06-openDebug
- Mybatis Interceptor 拦截器原理 源码分析
- SpringMVC interceptor拦截器配置使用(源码)
- 阿里路由框架--ARouter 源码解析之初始化ARouter
- ARouter源码解析01-编译生成文件
- ARouter源码解析02-加载路由表单
- ARouter源码解析03-路由跳转
- ARouter源码解析05-自动参数注入
- ARouter 依赖注入实现原理(源码解析)
- [源码]ARouter
- 深度解析Struts2拦截器Interceptor的设计原理
- 深度解析Struts2拦截器Interceptor的设计原理
- PHP中拦截器interceptor的使用解析
- python学习笔记(四)字典(dict)
- 1051. Pop Sequence (25)
- Java接口和抽象类的异同
- Hash表分析以及Java实现
- Python方法的几种常见参数类型
- ARouter源码解析04-interceptor拦截器
- CodeVS 1099 字串变换 题解
- 原生Android 嵌入 React Native 使用 Jenkins 打包遇到的坑
- SSM整合(SpringMVC、Spring、Mybatis)
- Linux 命令的符号及意义
- java 数组初始化
- springmvc(2)--环境搭建和配置前端控制器
- Network and Distributed System Security (NDSS) Symposium 2017
- USACO1.2.4 回文平方数