按照官网提供demo,定义一个TestInterceptor类,实现IInterceptor接口,实现process抽象方法。按照指导教程,在跳转的过程中应该会调用该方法,从而实现跳转拦截,但实际上自己写的demo怎么都不会走该方法。最后把官方demo的TestInterceptor类直接拿过来用,依然不行。
那就直接源码分析:
process()方法是在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);
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();
}
});
}
}
_excute在该类中的doInterceptions方法调用,通过调试,发现代码始终走不到最外面的if里面去,因为interceptors.size始终是0。
@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);
```
```
} catch (Exception e) {
callback.onInterrupt(e);
}
}
});
} else {
callback.onContinue(postcard);
}
}
进一步查看Warehouse类,发现interceptors 是一个list,大致可以猜出来,是用来保存自定义拦截器的list,如果自定义了两个interceptor,那这个list的size应该就是2。看一下是在什么时候add的。
static List<IInterceptor> interceptors = new ArrayList<>();
只有一个地方add元素,在InterceptorServiceImpl的init方法中,debug发现是Warehouse.interceptorsIndex始终为0,没有走到add。
@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);
···
···
}
那就再看看interceptorsIndex是什么。还是在Warehouse里面,可以看到interceptorsIndex 是一个以priority做key,IInterceptor对象做value的map。那就看看是什么时候put元素的
static Map<Integer, Class<? extends IInterceptor>> interceptorsIndex = new UniqueKeyTreeMap<>("More than one interceptors use same priority [%s]");
查看一下使用的地方,基本上都是被IInterceptorGroup接口中的loadInto抽象方法当做了参数,看到IInterceptorGroup和loadInto应该比较熟悉,如果看过Arouter拦截器原理分析,对这两个关键字应该不会陌生。
我们自定义了一个拦截器类的时候,Arouter会自动生成一个类,继承自IInterceptorGroup ,实现了loadInto方法,“Test1Interceptor.class”就是我定义的拦截器类。在这里通过loadInto方法将我们的拦截器相关信息加入到map中去。
/**
* DO NOT EDIT THIS FILE!!! IT WAS GENERATED BY AROUTER. */
public class ARouter$$Interceptors$$arouterdemo implements IInterceptorGroup {
@Override
public void loadInto(Map<Integer, Class<? extends IInterceptor>> interceptors) {
interceptors.put(7, Test1Interceptor.class);
}
}
继续debug,发现,这里没有被调用到,感觉莫名其妙,这个类都自动生成了,为什么还没有调用到这个方法,那就继续看这个方法是什么时候调用的。
在LogisticsCenter类中的registerInterceptor方法调用
private static void registerInterceptor(IInterceptorGroup interceptorGroup) {
markRegisteredByPlugin();
if (interceptorGroup != null) {
interceptorGroup.loadInto(Warehouse.interceptorsIndex);
}
}
registerInterceptor方法是在register方法里面调用
private static void register(String className) {
if (!TextUtils.isEmpty(className)) {
try {
Class<?> clazz = Class.forName(className);
Object obj = clazz.getConstructor().newInstance();
if (obj instanceof IRouteRoot) {
registerRouteRoot((IRouteRoot) obj);
} else if (obj instanceof IProviderGroup) {
registerProvider((IProviderGroup) obj);
} else if (obj instanceof IInterceptorGroup) {
registerInterceptor((IInterceptorGroup) obj);
} else {
logger.info(TAG, "register failed, class name: " + className
+ " should implements one of IRouteRoot/IProviderGroup/IInterceptorGroup.");
}
} catch (Exception e) {
logger.error(TAG,"register class error:" + className);
}
}
}
应该就是这里了,在debug,发现register竟然没有被调用到,而且在代码中也找不到register被调用到的地方。真的头大。于是又去看下github上的官方指导,发现这么几句话:
image.png
貌似这个插件可以自动注册。加上去试一下。
结果·····,竟然就好了。不是很明白括号后面的可选是什么意思。既然差了这个插件,拦截器就不能用了,为什么还是可选的。这个问题就这样处理了,所以下次遇到这样的问题,一定要多读文档,然后再看源码,不然效率太低了。
网友评论