Android-ARouter攔截器和IProvider解析

一、interceptor

使用ARouter的攔截器的話,會生成對應(yīng)的ARouter$$Providers$${模塊名}的class類,比如:

public class ARouter$$Interceptors$$aroutercomponent implements IInterceptorGroup {
  @Override
  public void loadInto(Map<Integer, Class<? extends IInterceptor>> interceptors) {
    interceptors.put(8, LoginInterceptor.class);
  }
}

在這里interceptors這個map集合中,以攔截器的優(yōu)先級作為key,攔截器的class作為value。定義攔截器的時候,并不會封裝成RouteMeta對象進(jìn)行保存。

二、IProvider

在ARouter中,service其實也是繼承自IProvider的接口,比如PathReplaceService、PretreatmentService、SerializationService等,都是繼承了IProvider的。
而IProvider的實現(xiàn)類,會被包裝成RouteMeta對象,包裝在ARouter$$Group$${組名}中,并且還會在ARouter$$Providers$${模塊名}中定義一份。

public class ARouter$$Group$$serializableservice implements IRouteGroup {
  @Override
  public void loadInto(Map<String, RouteMeta> atlas) {
    atlas.put("/serializableservice/hello", RouteMeta.build(RouteType.PROVIDER, HelloServiceImpl.class, "/serializableservice/hello", "serializableservice", null, -1, -2147483648));
    atlas.put("/serializableservice/json", RouteMeta.build(RouteType.PROVIDER, JsonServiceImpl.class, "/serializableservice/json", "serializableservice", null, -1, -2147483648));
    atlas.put("/serializableservice/pathReplace", RouteMeta.build(RouteType.PROVIDER, PathReplaceServiceImpl.class, "/serializableservice/pathreplace", "serializableservice", null, -1, -2147483648));
    atlas.put("/serializableservice/pretreatment", RouteMeta.build(RouteType.PROVIDER, PretreatmentServiceImpl.class, "/serializableservice/pretreatment", "serializableservice", null, -1, -2147483648));
  }
}
public class ARouter$$Providers$$ARouterBase implements IProviderGroup {
  @Override
  public void loadInto(Map<String, RouteMeta> providers) {
    providers.put("com.nene.arouterbase.service.HelloService", RouteMeta.build(RouteType.PROVIDER, HelloServiceImpl.class, "/serializableservice/hello", "serializableservice", null, -1, -2147483648));
    providers.put("com.alibaba.android.arouter.facade.service.SerializationService", RouteMeta.build(RouteType.PROVIDER, JsonServiceImpl.class, "/serializableservice/json", "serializableservice", null, -1, -2147483648));
    providers.put("com.alibaba.android.arouter.facade.service.PathReplaceService", RouteMeta.build(RouteType.PROVIDER, PathReplaceServiceImpl.class, "/serializableservice/pathReplace", "serializableservice", null, -1, -2147483648));
    providers.put("com.alibaba.android.arouter.facade.service.PretreatmentService", RouteMeta.build(RouteType.PROVIDER, PretreatmentServiceImpl.class, "/serializableservice/pretreatment", "serializableservice", null, -1, -2147483648));
  }
}

其實ARouter中的service,根據(jù)不同的Service來實現(xiàn)不同的操作,比如PretreatmentService預(yù)處理服務(wù),在調(diào)用navigation的時候,就會先判斷預(yù)處理服務(wù)是否為空,并且是否返回了false,如果是返回了false,則會在navigation中返回一個null。

_ARouter.navigation
    protected Object navigation(final Context context, final Postcard postcard, final int requestCode, final NavigationCallback callback) {
        PretreatmentService pretreatmentService = ARouter.getInstance().navigation(PretreatmentService.class);
        if (null != pretreatmentService && !pretreatmentService.onPretreatment(context, postcard)) {
            // Pretreatment failed, navigation canceled.
            return null;
        }
        ...
    }
PathReplaceService

而PathReplaceService的處理,其實就是在application對ARouter初始化的時候,會初始化一個InterceptorService,那么在這個時候就會判斷path是否需要替換。
而Activity的path是否需要被替換,則是通過在調(diào)用ARouter.getInstance().build("/news/news")的時候

// ARouter.java
    public Postcard build(String path) {
        return _ARouter.getInstance().build(path);
    }
// _ARouter.java
    protected Postcard build(String path) {
        if (TextUtils.isEmpty(path)) {
            throw new HandlerException(Consts.TAG + "Parameter is invalid!");
        } else {
            PathReplaceService pService = ARouter.getInstance().navigation(PathReplaceService.class);
            if (null != pService) {
                path = pService.forString(path);
            }
            return build(path, extractGroup(path), true);
        }
    }
SerializationService

SerializationService的調(diào)用,則是在Postcard調(diào)用withObject的時候,獲取到該service,然后通過該service的object2Json和parseObject來對數(shù)據(jù)進(jìn)行處理。
parseObject的調(diào)用,其實就是在針對對應(yīng)的Activity的屬性注解@Autowired的做處理的時候

public class NewsDesActivity$$ARouter$$Autowired implements ISyringe {
  private SerializationService serializationService;

  @Override
  public void inject(Object target) {
    serializationService = ARouter.getInstance().navigation(SerializationService.class);
    NewsDesActivity substitute = (NewsDesActivity)target;
    if (null != serializationService) {
      substitute.newsBean = serializationService.parseObject(substitute.getIntent().getStringExtra("newsBean"), new com.alibaba.android.arouter.facade.model.TypeWrapper<NewsBean>(){}.getType());
    } else {
      Log.e("ARouter::", "You want automatic inject the field 'newsBean' in class 'NewsDesActivity' , then you should implement 'SerializationService' to support object auto inject!");
    }
  }
}
ARouter的屬性注入

ARouter的屬性注入,還是需要在Activity中主動調(diào)用ARouter.getInstance().inject(this)
然后在這里會創(chuàng)建一個AutowiredService對象,用這個服務(wù)對象來處理ISyringe,其實就是對應(yīng)的Autowired,如下:

public class NewsDesActivity$$ARouter$$Autowired implements ISyringe {
  private SerializationService serializationService;

  @Override
  public void inject(Object target) {
    serializationService = ARouter.getInstance().navigation(SerializationService.class);
    NewsDesActivity substitute = (NewsDesActivity)target;
    if (null != serializationService) {
      substitute.newsBean = serializationService.parseObject(substitute.getIntent().getStringExtra("newsBean"), new com.alibaba.android.arouter.facade.model.TypeWrapper<NewsBean>(){}.getType());
    } else {
      Log.e("ARouter::", "You want automatic inject the field 'newsBean' in class 'NewsDesActivity' , then you should implement 'SerializationService' to support object auto inject!");
    }
  }
}

在這里就會調(diào)用ISyringe的inject方法,就可以對對應(yīng)的Activity(其實就是傳給inject方法的參數(shù)target)屬性注入對應(yīng)的值,這些屬性不能是私有的,否則就不能直接通過對應(yīng)的Activity對象直接拿到屬性。

三、初始化流程解析攔截器和IProvider

1.ARouter.init(this);

在Application的onCreate方法中,調(diào)用進(jìn)行初始化,其內(nèi)部實現(xiàn)如下:

    public static void init(Application application) {
        if (!hasInit) {
            logger = _ARouter.logger;
            _ARouter.logger.info(Consts.TAG, "ARouter init start.");
            hasInit = _ARouter.init(application);

            if (hasInit) {
                _ARouter.afterInit();
            }

            _ARouter.logger.info(Consts.TAG, "ARouter init over.");
        }
    }

而_ARouter.init(application);是初始化Warehouse中的各個集合的緩存內(nèi)容,將每個分組、Interceptor、Provider根據(jù)分組名和模塊名進(jìn)行文件的分別保存。
在初始化完成之后,就會調(diào)用_ARouter.afterInit();

2._ARouter.afterInit();

這里會初始化一個InterceptorService,這個是在ARouter-api中的InterceptorServiceImpl,如下所示:

ARouter-api中的InterceptorServiceImpl
@Route(path = "/arouter/service/interceptor")
public class InterceptorServiceImpl implements InterceptorService {
    private static boolean interceptorHasInit;
    private static final Object interceptorInitLock = new Object();

    @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 {
                        _execute(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);
        }
    }

    /**
     * Excute interceptor
     *
     * @param index    current interceptor index
     * @param counter  interceptor counter
     * @param postcard routeMeta
     */
    private static void _execute(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();
                    _execute(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();
                    // Be attention, maybe the thread in callback has been changed,
                    // then the catch block(L207) will be invalid.
                    // The worst is the thread changed to main thread, then the app will be crash, if you throw this exception!
//                    if (!Looper.getMainLooper().equals(Looper.myLooper())) {    // You shouldn't throw the exception if the thread is main thread.
//                        throw new HandlerException(exception.getMessage());
//                    }
                }
            });
        }
    }

    @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) {
                            throw new HandlerException(TAG + "ARouter init interceptor error! name = [" + interceptorClass.getName() + "], reason = [" + ex.getMessage() + "]");
                        }
                    }

                    interceptorHasInit = true;

                    logger.info(TAG, "ARouter interceptors init over.");

                    synchronized (interceptorInitLock) {
                        interceptorInitLock.notifyAll();
                    }
                }
            }
        });
    }

    private static void checkInterceptorsInitStatus() {
        synchronized (interceptorInitLock) {
            while (!interceptorHasInit) {
                try {
                    interceptorInitLock.wait(10 * 1000);
                } catch (InterruptedException e) {
                    throw new HandlerException(TAG + "Interceptor init cost too much time error! reason = [" + e.getMessage() + "]");
                }
            }
        }
    }
}
_ARouter.afterInit()
    static void afterInit() {
        // Trigger interceptor init, use byName.
        interceptorService = (InterceptorService) ARouter.getInstance().build("/arouter/service/interceptor").navigation();
    }

ARouter.getInstance().build("/arouter/service/interceptor")會返回一個Postcard對象,并且給Postcard的group和path賦值為arouter、/arouter/service/interceptor

    protected Postcard build(String path) {
        if (TextUtils.isEmpty(path)) {
            throw new HandlerException(Consts.TAG + "Parameter is invalid!");
        } else {
            PathReplaceService pService = ARouter.getInstance().navigation(PathReplaceService.class);
            if (null != pService) {
                path = pService.forString(path);
            }
            return build(path, extractGroup(path), true);
        }
    }

extractGroup方法就是在沒有單獨定義group的值的時候,從path中取出第一個/后面的第一串字符串作為group

    private String extractGroup(String path) {
        if (TextUtils.isEmpty(path) || !path.startsWith("/")) {
            throw new HandlerException(Consts.TAG + "Extract the default group failed, the path must be start with '/' and contain more than 2 '/'!");
        }

        try {
            String defaultGroup = path.substring(1, path.indexOf("/", 1));
            if (TextUtils.isEmpty(defaultGroup)) {
                throw new HandlerException(Consts.TAG + "Extract the default group failed! There's nothing between 2 '/'!");
            } else {
                return defaultGroup;
            }
        } catch (Exception e) {
            logger.warning(Consts.TAG, "Failed to extract default group! " + e.getMessage());
            return null;
        }
    }

在上面的build方法中,會先判斷有沒有設(shè)置了PathReplaceService,如果有設(shè)置了就會調(diào)用PathReplaceService.forString方法返回新的path,如果沒有設(shè)置則會使用原來的path,這也就是路徑替換的功能的實現(xiàn)。

3.Postcard.navigation

navigation有多個重載的方法,而最終都會執(zhí)行_ARouter的navigation(final Context context, final Postcard postcard, final int requestCode, final NavigationCallback callback)方法,就是通過ARouter的navigation調(diào)用_ARouter的navigation方法。

    public Object navigation(Context mContext, Postcard postcard, int requestCode, NavigationCallback callback) {
        return _ARouter.getInstance().navigation(mContext, postcard, requestCode, callback);
    }

而_ARouter的navigation方法實現(xiàn)如下:

    protected Object navigation(final Context context, final Postcard postcard, final int requestCode, final NavigationCallback callback) {
        PretreatmentService pretreatmentService = ARouter.getInstance().navigation(PretreatmentService.class);
        if (null != pretreatmentService && !pretreatmentService.onPretreatment(context, postcard)) {
            // Pretreatment failed, navigation canceled.
            return null;
        }

        try {
            // 在這里最終會把每個group下的RouteMeta保存在Warehouse.routes中
            LogisticsCenter.completion(postcard);
        } catch (NoRouteFoundException ex) {
            logger.warning(Consts.TAG, ex.getMessage());

            if (debuggable()) {
                // Show friendly tips for user.
                runInMainThread(new Runnable() {
                    @Override
                    public void run() {
                        Toast.makeText(mContext, "There's no route matched!\n" +
                                " Path = [" + postcard.getPath() + "]\n" +
                                " Group = [" + postcard.getGroup() + "]", Toast.LENGTH_LONG).show();
                    }
                });
            }

            if (null != callback) {
                callback.onLost(postcard);
            } else {
                // No callback for this invoke, then we use the global degrade service.
                DegradeService degradeService = ARouter.getInstance().navigation(DegradeService.class);
                if (null != degradeService) {
                    degradeService.onLost(context, postcard);
                }
            }

            return null;
        }

        if (null != callback) {
            callback.onFound(postcard);
        }

        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());
                }
            });
        } else {
            return _navigation(context, postcard, requestCode, callback);
        }

        return null;
    }
public synchronized static void completion(Postcard postcard) {
    //第一次進(jìn)來是拿不到RouteMeta信息的,因為routes是空的
    RouteMeta routeMeta = Warehouse.routes.get(postcard.getPath());
    if (null == routeMeta) {
        //我們傳過來的postcard的group是arouter、path是/arouter/service/interceptor
        //我們在groupIndex中找對應(yīng)的groupMeta,其實看到這的時候,我們默認(rèn)是沒有root為arouter的組,只能去arouter默認(rèn)提供的root中找
        Class<? extends IRouteGroup> groupMeta = Warehouse.groupsIndex.get(postcard.getGroup());  // Load route meta.
        if (null == groupMeta) {
        } else {
            try {
                //反射拿到ARouter$$Group$$arouter
                IRouteGroup iGroupInstance = groupMeta.getConstructor().newInstance();
                //所以最終把InterceptorServiceImpl放到了Warehouse.routes中
                iGroupInstance.loadInto(Warehouse.routes);
                //用完groupsIndex對應(yīng)的IRouteGroup信息后,從map中移除掉,下次就直接從routes中去拿了
                Warehouse.groupsIndex.remove(postcard.getGroup());

            } catch (Exception e) {
                throw new HandlerException(TAG + "Fatal exception when loading group meta. [" + e.getMessage() + "]");
            }
            //繼續(xù)走一遍completion,下次會走下面的else
            completion(postcard);
        }
    } else {
        //對postCard屬性賦值
        postcard.setDestination(routeMeta.getDestination());
        postcard.setType(routeMeta.getType());
        postcard.setPriority(routeMeta.getPriority());
        postcard.setExtra(routeMeta.getExtra());

        Uri rawUri = postcard.getUri();
        //默認(rèn)uri為空
        if (null != rawUri) {  
            Map<String, String> resultMap = TextUtils.splitQueryParameters(rawUri);
            Map<String, Integer> paramsType = routeMeta.getParamsType();

            if (MapUtils.isNotEmpty(paramsType)) {
                for (Map.Entry<String, Integer> params : paramsType.entrySet()) {
                    setValue(postcard,
                            params.getValue(),
                            params.getKey(),
                            resultMap.get(params.getKey()));
                }

                // Save params name which need auto inject.
                postcard.getExtras().putStringArray(ARouter.AUTO_INJECT, paramsType.keySet().toArray(new String[]{}));
            }

            // Save raw uri
            postcard.withString(ARouter.RAW_URI, rawUri.toString());
        }

        switch (routeMeta.getType()) {
            //由于InterceptorServiceImpl是provider類型的
            case PROVIDER:
                Class<? extends IProvider> providerMeta = (Class<? extends IProvider>) routeMeta.getDestination();
                //拿對應(yīng)的provider
                IProvider instance = Warehouse.providers.get(providerMeta);
                if (null == instance) {
                    IProvider provider;
                    try {
                        //反射創(chuàng)建InterceptorServiceImpl
                        provider = providerMeta.getConstructor().newInstance();
                        //調(diào)用InterceptorServiceImpl的init方法
                        provider.init(mContext);
                        Warehouse.providers.put(providerMeta, provider);
                        instance = provider;
                    } catch (Exception e) {
                        throw new HandlerException("Init provider failed! " + e.getMessage());
                    }
                }
                //給postcard賦值
                postcard.setProvider(instance);
                postcard.greenChannel();
                break;
            case FRAGMENT:
                postcard.greenChannel();
            default:
                break;
        }
    }
}

這個過程需要注意,是對/arouter/service/interceptor這個interceptor服務(wù)轉(zhuǎn)成RouteMeta,這個其實就是在alibaba:arouter-api這個庫里生成的。


image.png
public class ARouter$$Group$$arouter implements IRouteGroup {
    public ARouter$$Group$$arouter() {
    }

    public void loadInto(Map<String, RouteMeta> atlas) {
        atlas.put("/arouter/service/autowired", RouteMeta.build(RouteType.PROVIDER, AutowiredServiceImpl.class, "/arouter/service/autowired", "arouter", (Map)null, -1, -2147483648));
        atlas.put("/arouter/service/interceptor", RouteMeta.build(RouteType.PROVIDER, InterceptorServiceImpl.class, "/arouter/service/interceptor", "arouter", (Map)null, -1, -2147483648));
    }
}

上面的這個過程,就是會從Warehouse.groupsIndex中把ARouter$$Group$$arouter加入到其中,然后在LogisticsCenter.completion方法中,取出這個分組,然后將arouter這個分組中的RouteMeta保存在Warehouse.routes中。這樣就對interceptorService進(jìn)行了初始化,其實就是InterceptorServiceImpl實例。
由于InterceptorServiceImpl的type是PROVIDER,所以在completion(postcard)方法中處理完第一個if分支之后,因為把分組內(nèi)容從緩存中remove了,則會執(zhí)行else分支,因為type是PROVIDER的原因,所以providerMeta是InterceptorServiceImpl類型的,然后去Warehouse.providers拿,此時是空的,所以通過反射創(chuàng)建InterceptorServiceImpl對象,創(chuàng)建完調(diào)用InterceptorServiceImpl調(diào)用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) {
                            throw new HandlerException(TAG + "ARouter init interceptor error! name = [" + interceptorClass.getName() + "], reason = [" + ex.getMessage() + "]");
                        }
                    }

                    interceptorHasInit = true;

                    logger.info(TAG, "ARouter interceptors init over.");

                    synchronized (interceptorInitLock) {
                        interceptorInitLock.notifyAll();
                    }
                }
            }
        });
    }

在這里就會初始化攔截器,接著就會繼續(xù)回到_ARouter.navigation方法中調(diào)用LogisticsCenter.completion(postcard);初始化完成RouteMeta完成之后,繼續(xù)執(zhí)行interceptorService.doInterceptions的調(diào)用。如下:

    protected Object navigation(final Context context, final Postcard postcard, final int requestCode, final NavigationCallback callback) {
        ...

        if (null != callback) {
            callback.onFound(postcard);
        }

        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());
                }
            });
        } else {
            return _navigation(context, postcard, requestCode, callback);
        }

        return null;
    }

在這里就會調(diào)用InterceptorServiceImpl的doInterceptions,將要執(zhí)行的RouteMeta進(jìn)行分發(fā)判斷是否執(zhí)行攔截器。
看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 {
                        // 調(diào)用InterceptorServiceImpl的方法
                        _execute(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);
        }
    }
    private static void _execute(final int index, final CancelableCountDownLatch counter, final Postcard postcard) {
        if (index < Warehouse.interceptors.size()) {
            // 取出攔截器,并且調(diào)用攔截器的process方法
            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();
                    _execute(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();
                    // Be attention, maybe the thread in callback has been changed,
                    // then the catch block(L207) will be invalid.
                    // The worst is the thread changed to main thread, then the app will be crash, if you throw this exception!
//                    if (!Looper.getMainLooper().equals(Looper.myLooper())) {    // You shouldn't throw the exception if the thread is main thread.
//                        throw new HandlerException(exception.getMessage());
//                    }
                }
            });
        }
    }

到這里,就可以看到對攔截器的觸發(fā)。
攔截器其實是在ARouter.init()方法中調(diào)用_ARouter.afterInit()方法初始化了InterceptorService實例,然后在具體的執(zhí)行路由的時候,就會調(diào)用InterceptorService實例觸發(fā)攔截器的執(zhí)行。

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

相關(guān)閱讀更多精彩內(nèi)容

  • 一、ARouter ARouter使用的是APT(Annotation Processing Tool)注解處理器...
    zzq_nene閱讀 2,437評論 0 0
  • 前言 隨著項目業(yè)務(wù)邏輯和功能點日益遞增, 邏輯的耦合程度也逐漸升高, 組件化技術(shù)可以很好的解決這個問題, 公司大佬...
    SharryChoo閱讀 1,185評論 0 9
  • 今天我們接著來拆下ARouter的攔截器,這個是ARouter路由框架的第六篇分享了。在Android系統(tǒng)自帶的s...
    juexingzhe閱讀 18,107評論 2 19
  • 組件化被越來越多的Android項目采用,而作為組件化的基礎(chǔ)——路由也是重中之重。本篇文章將詳細(xì)的分析阿里巴巴開源...
    胡奚冰閱讀 15,024評論 8 32
  • ARouter ARouter 是阿里云出品的Android中間件,負(fù)責(zé)處理盅跳轉(zhuǎn)頁面時的邏輯,簡化和優(yōu)化之前跳轉(zhuǎn)...
    常強兒閱讀 9,087評論 1 1

友情鏈接更多精彩內(nèi)容