ARouter攔截器無(wú)法生效的解決辦法

按照官網(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)這么幾句話:


image.png

貌似這個(gè)插件可以自動(dòng)注冊(cè)。加上去試一下。
結(jié)果·····,竟然就好了。不是很明白括號(hào)后面的可選是什么意思。既然差了這個(gè)插件,攔截器就不能用了,為什么還是可選的。這個(gè)問(wèn)題就這樣處理了,所以下次遇到這樣的問(wèn)題,一定要多讀文檔,然后再看源碼,不然效率太低了。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容

  • 今天我們接著來(lái)拆下ARouter的攔截器,這個(gè)是ARouter路由框架的第六篇分享了。在Android系統(tǒng)自帶的s...
    juexingzhe閱讀 17,948評(píng)論 2 19
  • ARouter是什么 ARouter是阿里巴巴開(kāi)源的Android平臺(tái)中對(duì)頁(yè)面、服務(wù)提供路由功能的中間件,提倡的是...
    雪寶Wu閱讀 7,021評(píng)論 0 64
  • Arouter框架適合項(xiàng)目比較大,模塊多的時(shí)候,可以實(shí)現(xiàn)解耦,不需要知道跳轉(zhuǎn)的是哪個(gè)activity,只需要知道配...
    破曉11閱讀 3,483評(píng)論 0 2
  • 組件化被越來(lái)越多的Android項(xiàng)目采用,而作為組件化的基礎(chǔ)——路由也是重中之重。本篇文章將詳細(xì)的分析阿里巴巴開(kāi)源...
    胡奚冰閱讀 14,854評(píng)論 8 32
  • 我不是佛教的信徒,對(duì)佛教中的很多說(shuō)法都很陌生,這本書(shū)不一定是自己能夠讀得很懂的一本,之所以選擇讀《西藏生死書(shū)》,僅...
    陸拾雜記閱讀 1,967評(píng)論 1 42