ARouter源码解析04-interceptor拦截器

上篇文章我们分析了ARouter的路由跳转,这篇文章我们来分析interceptor拦截器。

首先,同样在IDE编译过程中,拦截器也会产生相应的文件。(详见ARouter源码解析01-编译生成文件)

public class ARouter$$Interceptors$$app implements IInterceptorGroup {
  @Override
  public void loadInto(Map> interceptors) {
    interceptors.put(3, Test2Interceptor.class);
    interceptors.put(5, Test3Interceptor.class);
    interceptors.put(7, Test1Interceptor.class);
  }
}  

可以看到,这里根据priority将Intercepter按照级别进行排序,级别从高到第依次put到interceptors集合中。那么,这些intercepter是在什么地方加载到内存中的呢?

同时,我们知道,拦截器有个init()方法,会在程序初始化的时候,进行调用,那么,是在哪里执行拦截器的init()方法的呢?
再回到ARouter.init()来看

public static void init(Application application) {
//...
hasInit = _ARouter.init(application);
if (hasInit) {
    _ARouter.afterInit();
}
//...

}

这里有个afterInit方法,我们跟进去看下

static void afterInit() {
   // Trigger interceptor init, use byName.
   interceptorService = (InterceptorService) ARouter.getInstance().build("/arouter/service/interceptor").navigation();
}  

这里,通过路由跳转,调用了InterceptorServiceImpl,但是在路由app模块build文件中,并没有/arouter/service/interceptor这个路由表单,那么ARouter这里是通过怎么跳转的呢?

原来,在aroute-api中,还有个arouter的build文件,在这个文件下,有着和app模块下build包名相同的ARouter开头的几个文件(故ARouter.init的时候,也会把这几个路由表单加载进去)

package com.alibaba.android.arouter.routes;

public class ARouter$$Group$$arouter implements IRouteGroup {
  @Override
  public void loadInto(Map atlas) {
    atlas.put("/arouter/service/autowired", RouteMeta.build(RouteType.PROVIDER, AutowiredServiceImpl.class, "/arouter/service/autowired", "arouter", null, -1, -2147483648));
    atlas.put("/arouter/service/interceptor", RouteMeta.build(RouteType.PROVIDER, InterceptorServiceImpl.class, "/arouter/service/interceptor", "arouter", null, -1, -2147483648));
  }
}

我们再来在InterceptorServiceImpl,首先会在navigation的时候调用 LogisticsCenter.completion从而调用provider.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> entry : Warehouse.interceptorsIndex.entrySet()) {
                    Class 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;

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

可以发现,大体的,就是通过线程池.execute(),在异步线程中,获取所有的拦截器IInterceptor,调用他们的init方法,并把拦截器添加到Warehouse.interceptors集合中。

知道了

接着,继续在navigation方法中,如果没有把postcard.isGreenChannel设为true,那么调用interceptorService.doInterceptions执行拦截器,处理是否拦截。

完成了拦截器的init(),再来看navigation的时候,拦截器的拦截,

final class _ARouter {
    protected Object navigation(final Context context, final Postcard postcard, final int requestCode, final NavigationCallback callback) {
        LogisticsCenter.completion(postcard);
        //isGreenChannel為ture,說明不需要interceptor,要跳過interceptor
        if (!postcard.isGreenChannel()) {
            interceptorService.doInterceptions(postcard, new InterceptorCallback() {
                @Override
                public void onContinue(Postcard postcard) {
                    _navigation(context, postcard, requestCode, callback);
                }

                @Override
                public void onInterrupt(Throwable exception) {
                    if (null != callback) {
                        callback.onInterrupt(postcard);
                    }
                }
            });
        } else {
            return _navigation(context, postcard, requestCode, callback);
        }

        return null;
    }
}  

来看doInterceptions(),这里进行拦截器的拦截,会遍历拦截器列表,并调用拦截器的process(),最终,根据结果回调onContinue或onInterrupt来继续navigation或终止navigation。

@Override
public void doInterceptions(final Postcard postcard, final InterceptorCallback callback) {
    // 检查拦截器列表是否为空
    if (CollectionUtils.isNotEmpty(Warehouse.interceptors)) {
        // 等待拦截器服务完成初始化
        // ......

        LogisticsCenter.executor.execute(new Runnable() {
            @Override
            public void run() {
                // CountDown倒数计数器
                CancelableCountDownLatch interceptorCounter = new CancelableCountDownLatch(Warehouse.interceptors.size());
                try {
                    // 在另一个线程中递归依次执行拦截器操作
                    _excute(0, interceptorCounter, postcard);
                    // 等待超时
                    interceptorCounter.await(postcard.getTimeout(), TimeUnit.SECONDS);
                    // 倒数计时器不为0,表示还有拦截器未执行完成
                    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 _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();
            }
        });
    }
}  

至此,即完成了interceptor的拦截,下篇文章,我们来解析ARouter的自动注入参数的功能。

你可能感兴趣的:(ARouter源码)