ARouter攔截器無法生效的解決辦法

按照官網(wǎng)提供demo,定義一個TestInterceptor類,實現(xiàn)IInterceptor接口,實現(xiàn)process抽象方法。按照指導教程,在跳轉的過程中應該會調用該方法,從而實現(xiàn)跳轉攔截,但實際上自己寫的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方法調用,通過調試,發(fā)現(xiàn)代碼始終走不到最外面的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類,發(fā)現(xiàn)interceptors 是一個list,大致可以猜出來,是用來保存自定義攔截器的list,如果自定義了兩個interceptor,那這個list的size應該就是2。看一下是在什么時候add的。

 static List<IInterceptor> interceptors = new ArrayList<>();

只有一個地方add元素,在InterceptorServiceImpl的init方法中,debug發(fā)現(xiàn)是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抽象方法當做了參數(shù),看到IInterceptorGroup和loadInto應該比較熟悉,如果看過Arouter攔截器原理分析,對這兩個關鍵字應該不會陌生。
我們自定義了一個攔截器類的時候,Arouter會自動生成一個類,繼承自IInterceptorGroup ,實現(xiàn)了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);
}
}

繼續(xù)debug,發(fā)現(xiàn),這里沒有被調用到,感覺莫名其妙,這個類都自動生成了,為什么還沒有調用到這個方法,那就繼續(xù)看這個方法是什么時候調用的。

在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,發(fā)現(xiàn)register竟然沒有被調用到,而且在代碼中也找不到register被調用到的地方。真的頭大。于是又去看下github上的官方指導,發(fā)現(xiàn)這么幾句話:


image.png

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

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

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

友情鏈接更多精彩內容