按照官網(wǎng)提供demo,定義一個(gè)TestInterceptor類(lèi),實(shí)現(xiàn)IInterceptor接口,實(shí)現(xiàn)process抽象方法。按照指導(dǎo)教程,在跳轉(zhuǎn)的過(guò)程中應(yīng)該會(huì)調(diào)用該方法,從而實(shí)現(xiàn)跳轉(zhuǎn)攔截,但實(shí)際上自己寫(xiě)的demo怎么都不會(huì)走該方法。最后把官方demo的TestInterceptor類(lèi)直接拿過(guò)來(lái)用,依然不行。
那就直接源碼分析:
process()方法是在InterceptorServiceImpl中_excute方法調(diào)用。
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在該類(lèi)中的doInterceptions方法調(diào)用,通過(guò)調(diào)試,發(fā)現(xiàn)代碼始終走不到最外面的if里面去,因?yàn)閕nterceptors.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);
}
}
進(jìn)一步查看Warehouse類(lèi),發(fā)現(xiàn)interceptors 是一個(gè)list,大致可以猜出來(lái),是用來(lái)保存自定義攔截器的list,如果自定義了兩個(gè)interceptor,那這個(gè)list的size應(yīng)該就是2。看一下是在什么時(shí)候add的。
static List<IInterceptor> interceptors = new ArrayList<>();
只有一個(gè)地方add元素,在InterceptorServiceImpl的init方法中,debug發(fā)現(xiàn)是Warehouse.interceptorsIndex始終為0,沒(méi)有走到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 是一個(gè)以priority做key,IInterceptor對(duì)象做value的map。那就看看是什么時(shí)候put元素的
static Map<Integer, Class<? extends IInterceptor>> interceptorsIndex = new UniqueKeyTreeMap<>("More than one interceptors use same priority [%s]");
查看一下使用的地方,基本上都是被IInterceptorGroup接口中的loadInto抽象方法當(dāng)做了參數(shù),看到IInterceptorGroup和loadInto應(yīng)該比較熟悉,如果看過(guò)Arouter攔截器原理分析,對(duì)這兩個(gè)關(guān)鍵字應(yīng)該不會(huì)陌生。
我們自定義了一個(gè)攔截器類(lèi)的時(shí)候,Arouter會(huì)自動(dòng)生成一個(gè)類(lèi),繼承自IInterceptorGroup ,實(shí)現(xiàn)了loadInto方法,“Test1Interceptor.class”就是我定義的攔截器類(lèi)。在這里通過(guò)loadInto方法將我們的攔截器相關(guān)信息加入到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);
}
}
繼續(xù)debug,發(fā)現(xiàn),這里沒(méi)有被調(diào)用到,感覺(jué)莫名其妙,這個(gè)類(lèi)都自動(dòng)生成了,為什么還沒(méi)有調(diào)用到這個(gè)方法,那就繼續(xù)看這個(gè)方法是什么時(shí)候調(diào)用的。
在LogisticsCenter類(lèi)中的registerInterceptor方法調(diào)用
private static void registerInterceptor(IInterceptorGroup interceptorGroup) {
markRegisteredByPlugin();
if (interceptorGroup != null) {
interceptorGroup.loadInto(Warehouse.interceptorsIndex);
}
}
registerInterceptor方法是在register方法里面調(diào)用
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);
}
}
}
應(yīng)該就是這里了,在debug,發(fā)現(xiàn)register竟然沒(méi)有被調(diào)用到,而且在代碼中也找不到register被調(diào)用到的地方。真的頭大。于是又去看下github上的官方指導(dǎo),發(fā)現(xiàn)這么幾句話:
貌似這個(gè)插件可以自動(dòng)注冊(cè)。加上去試一下。
結(jié)果·····,竟然就好了。不是很明白括號(hào)后面的可選是什么意思。既然差了這個(gè)插件,攔截器就不能用了,為什么還是可選的。這個(gè)問(wèn)題就這樣處理了,所以下次遇到這樣的問(wèn)題,一定要多讀文檔,然后再看源碼,不然效率太低了。