在初始化的时候,还有一处没有分析
if (hasInit) {
_ARouter.afterInit();
}
static void afterInit() {
interceptorService = (InterceptorService) ARouter.getInstance().build("/arouter/service/interceptor").navigation();
}
在源码的解释是出发拦截器的初始化。
LogisticsCenter.completion(postcard);
public synchronized static void completion(Postcard postcard) {
switch (routeMeta.getType()) {
// 是provider类型的目标类必须实现IProvider的接口
case PROVIDER:
//获取provider目标类的Class对象
Class<? extends IProvider> providerMeta = (Class<? extends IProvider>) 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.init(mContext);
// 存储 目标类的数据和目标类的实例的映射关系
Warehouse.providers.put(providerMeta, provider);
instance = provider;
} catch (Exception e) {
throw new HandlerException("Init provider failed! " + e.getMessage());
}
}
// 当是provider类型的时候,把获取到的目标类的实例设置到Postcard中,
postcard.setProvider(instance);
// 设置是绿色通道 ---> 所谓的绿色的通道就是不用去执行拦截器的逻辑
postcard.greenChannel();
break;
case FRAGMENT:
//同样是fragment类别的 也是绿色通道的
postcard.greenChannel();
default:
break;
}
}
}
在completion方法中,如果类型是PROVIDER,而InterceptorService是继承IProvider的接口,所以当获取provider目标类的Class对象为空的时候,会调用provider.init(mContext),provider的具体实现类是InterceptorServiceImpl,因此为调用InterceptorServiceImpl的init().
InterceptorServiceImpl # init
@Override
public 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) {
}
}
interceptorHasInit = true;
synchronized (interceptorInitLock) {
interceptorInitLock.notifyAll();
}
}
}
});
}
主要是用反射获取到实例,而这个实例使我们自定义的拦截器的实例。
然后将自定义的实例填充到interceptors的集合中,然后将interceptorHasInit置为true,表示拦截器初始化完毕。
当正常我们进行页面跳转的时候,不是绿色通道需要去调用InterceptorServiceImpl中的doInterceptions()
_Arouter # navigation
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(context, 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());
}
});
有上面可知,拦截器在异步线程里执行,不然太多的拦截器可能会造成ANR。
InterceptorServiceImpl # doInterceptions
@Override
public void doInterceptions(final Postcard postcard, final InterceptorCallback callback) {
if (null != Warehouse.interceptors && Warehouse.interceptors.size() > 0) {
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 {
_excute(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(new HandlerException(postcard.getTag().toString()));
} else {
callback.onContinue(postcard);
}
} catch (Exception e) {
callback.onInterrupt(e);
}
}
});
} else {
callback.onContinue(postcard);
}
}
会开启一个线程池去执行拦截器中的逻辑。
InterceptorServiceImpl # _excute
private static void _excute(final int index, final CancelableCountDownLatch counter, final Postcard postcard) {
if (index < Warehouse.interceptors.size()) {
//拿到我们自定义的拦截器
IInterceptor iInterceptor = Warehouse.interceptors.get(index);
//执行自定义拦截器的 process()方法
iInterceptor.process(postcard, new InterceptorCallback() {
@Override
public void onContinue(Postcard postcard) {
counter.countDown();
_excute(index + 1, counter, postcard);
}
@Override
public void onInterrupt(Throwable exception) {
postcard.setTag(null == exception ? new HandlerException("No message.") : exception.getMessage()); // save the exception message for backup.
counter.cancel();
}
}
});
}
}
依次取出拦截器实例,然后调用拦截器的process方法,传入回调接口 InterceptorCallBack
正常的话就会走 onCointinue()方法 然后重新执行 _execute()方法只不过需要将index+1了,依次执行process的方法。
在我们自定义的拦截器中,会设置一个优先级。
@Interceptor(priority = 1)
public class TestInterceptor implements IInterceptor {}
注解中的 priority属性值 越小会被先执行
。这个跟我们数据仓库中 Warehouse # interceptorIndex有关系 它是一个红黑树结构的集合是按照顺序存储的,key是以priority,value是我们自定义拦截器的Class对象
当我们从interceptorIndex取出Class对象的时候,是按照 存储的优先级拿到的
网友评论