public interface IInterceptor extends IProvider {
/**
* The operation of this interceptor.
*
* @param postcard meta
* @param callback cb
*/
void process(Postcard postcard, InterceptorCallback callback);
}
IProvider也是一个接口里面只有一个init方法
public interface IProvider {
/**
* Do your init work in this method, it well be call when processor has been load.
*
* @param context ctx
*/
void init(Context context);
}
Ctrl+左键点击init方法查看一下,发现了InterceptorServiceImpl类,是一个接口InterceptorService实现类
@Route(path = "/arouter/service/interceptor")
public class InterceptorServiceImpl implements InterceptorService {
InterceptorService也是一个继承自IProvider 接口的接口,有一个 doInterceptions方法,接受两个参数
Postcard和InterceptorCallback这个方法的参数和我们需要实现的IInterceptor接口的process的参数一样,
可以猜测是通过InterceptorServiceImpl 拦截ARouter的navigation然后调用IInterceptor.process来通知的。
/**
* Do interceptions
*/
void doInterceptions(Postcard postcard, InterceptorCallback callback);
回到InterceptorServiceImpl 看一下InterceptorServiceImpl.init是在哪里被调用的
发现是在LogisticsCenter的completion方法中
switch (routeMeta.getType()) {
case PROVIDER: // if the route is provider, should find its instance
// Its provider, so it must implement IProvider
Class<? extends IProvider> providerMeta = (Class<? extends IProvider>) routeMeta.getDestination();
IProvider instance = Warehouse.providers.get(providerMeta);
if (null == instance) { // There's no instance of this provider
IProvider provider;
try {
provider = providerMeta.getConstructor().newInstance();
provider.init(mContext);
Warehouse.providers.put(providerMeta, provider);
instance = provider;
} catch (Exception e) {
throw new HandlerException("Init provider failed! " + e.getMessage());
}
}
postcard.setProvider(instance);
postcard.greenChannel(); // Provider should skip all of interceptors
break;
继续往上找completion被调用的地方
发现是在_ARouter类中的navigation方法中,这个方法有一个重载,两种不同形式都调用了completion
protected <T> T navigation(Class<? extends T> service)
protected Object navigation(final Context context, final Postcard postcard, final int requestCode, final NavigationCallback callback)
根据参数的不同形式可以简单猜测一下返回泛型的方法对应的是Service、返回Object类型方法对应的是Activity
继续往上看
/**
* Launch the navigation by type
*
* @param service interface of service
* @param return type
* @return instance of service
*/
public <T> T navigation(Class<? extends T> service) {
return _ARouter.getInstance().navigation(service);
}
/**
* Launch the navigation.
*
* @param mContext .
* @param postcard .
* @param requestCode Set for startActivityForResult
* @param callback cb
*/
public Object navigation(Context mContext, Postcard postcard, int requestCode, NavigationCallback callback) {
return _ARouter.getInstance().navigation(mContext, postcard, requestCode, callback);
}
感觉和猜想的比较接近,被调用的地方已经是熟悉的ARouter类中了。
点开_ARouter类的代码,发现类最开始的注释中是这么写的ARouter core (Facade patten),
这个类是ARouter的核心,使用了门面模式
简单调用ARouter.getInstance().Build().navigation()发现确实调用的是_ARouter类中Object返回类型的navigation()方法,所以从这个方法开始查看navigation时具体做了什么
/**
* Use router navigation.
*
* @param context Activity or null.
* @param postcard Route metas
* @param requestCode RequestCode
* @param callback cb
*/
protected Object navigation(final Context context, final Postcard postcard, final int requestCode, final NavigationCallback callback) {
PretreatmentService pretreatmentService = ARouter.getInstance().navigation(PretreatmentService.class);
传入了PretreatmentService.class作为参数调用了泛型返回类型的navigation方法
/**
* Launch the navigation by type
*
* @param service interface of service
* @param return type
* @return instance of service
*/
public <T> T navigation(Class<? extends T> service) {
return _ARouter.getInstance().navigation(service);
}
看一下PretreatmentService类,
/**
* Pretreatment service used for check if need navigation.
*
* @author zhilong [Contact me.](mailto:[email protected])
* @version 1.0
* @since 2019-05-08 11:53
*/
public interface PretreatmentService extends IProvider {
/**
* Do something before navigation.
*
* @param context context
* @param postcard meta
* @return if need navigation.
*/
boolean onPretreatment(Context context, Postcard postcard);
}
注释的字面意思是通过这个Service来预处理判断是否需要navigation
返回泛型的Navigation方法中的代码量不多
protected <T> T navigation(Class<? extends T> service) {
try {
Postcard postcard = LogisticsCenter.buildProvider(service.getName());
// Compatible 1.0.5 compiler sdk.
// Earlier versions did not use the fully qualified name to get the service
if (null == postcard) {
// No service, or this service in old version.
postcard = LogisticsCenter.buildProvider(service.getSimpleName());
}
if (null == postcard) {
return null;
}
LogisticsCenter.completion(postcard);
return (T) postcard.getProvider();
} catch (NoRouteFoundException ex) {
logger.warning(Consts.TAG, ex.getMessage());
return null;
}
}
先通过LogisticsCenter.buildProvider(service.getName())方法获得PostCard实例不行的话就通过
postcard = LogisticsCenter.buildProvider(service.getSimpleName())方法来获得一个PostCard实例然后作为参数传给之前看到的LogisticsCenter.completion(postcard)方法
completion方法中会用到RouteMeta实例然后判断是否为null,不为null就对PostCard中的Destination、Type、Priority、Extra、Uri等参数进行设置然后如果是IProvider的话会通过RouteMeta反射生成IProvider对应的实现类,把以实现类的Class作为键,实例作为制保存到Warehouse的静态HashMap中,最后会对传进来的PostCard 实例设置GreenChannel信息,
如果是Fragment,就只设置GreenChannel信息
switch (routeMeta.getType()) {
case PROVIDER: // if the route is provider, should find its instance
// Its provider, so it must implement IProvider
Class<? extends IProvider> providerMeta = (Class<? extends IProvider>) routeMeta.getDestination();
IProvider instance = Warehouse.providers.get(providerMeta);
if (null == instance) { // There's no instance of this provider
IProvider provider;
try {
provider = providerMeta.getConstructor().newInstance();
provider.init(mContext);
Warehouse.providers.put(providerMeta, provider);
instance = provider;
} catch (Exception e) {
throw new HandlerException("Init provider failed! " + e.getMessage());
}
}
postcard.setProvider(instance);
postcard.greenChannel(); // Provider should skip all of interceptors
break;
case FRAGMENT:
postcard.greenChannel(); // Fragment needn't interceptors
default:
break;
}
WareHourse代码
/**
* Storage of route meta and other data.
*
* @author zhilong Contact me.
* @version 1.0
* @since 2017/2/23 下午1:39
*/
class Warehouse {
// Cache route and metas
static Map<String, Class<? extends IRouteGroup>> groupsIndex = new HashMap<>();
static Map<String, RouteMeta> routes = new HashMap<>();
// Cache provider
static Map<Class, IProvider> providers = new HashMap<>();
static Map<String, RouteMeta> providersIndex = new HashMap<>();
// Cache interceptor
static Map<Integer, Class<? extends IInterceptor>> interceptorsIndex = new UniqueKeyTreeMap<>("More than one interceptors use same priority [%s]");
static List<IInterceptor> interceptors = new ArrayList<>();
static void clear() {
routes.clear();
groupsIndex.clear();
providers.clear();
providersIndex.clear();
interceptors.clear();
interceptorsIndex.clear();
}
}
所以 PretreatmentService pretreatmentService = ARouter.getInstance().navigation(PretreatmentService.class);
这行代码就是对navigation一系列预处理
接下来
LogisticsCenter.completion(postcard);这里的postcard是ARouter.getInstance().Build()产生的这个PostCard
从之前分析知道就是对路由信息的一些处理
然后可以看到不是greenChannel就会拦截
if (!postcard.isGreenChannel()) { // It must be run in async thread, maybe interceptor cost too mush time made ANR.
interceptorService.doInterceptions(postcard, new InterceptorCallback() {
大致能够知道了,之所以能够拦截是因为ARouter在navigation之前有先做拦截。
看一眼interceptorService是什么,发现就是InterceptorService接口的实现类的引用
回顾开头看到的,这里的就说明了为什么ARouter路由拦截实现IInterceptor接口就可以了
那么还是得关注一下,实现的IInterceptor实现类是什么时候和_ARouter类关联起来的。
很容易想到的就是在App onCreate方法中我们需要调用的ARouter.init()
/**
* Init, it must be call before used router.
*/
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本身使用了门面模式ARouter.init(Application application)实际的处理者是_ARouter,自然看一下_ARouter.init和_ARouter类,_ARouter中有一个DefaultPoolExecutor类型的静态成员变量,它是ThreadPoolExecutor的子类,还有一个静态成员变量Handler、InterceptorService实现类以及_ARouter本身。可见_ARouter是一个单例实现
final class _ARouter {
static ILogger logger = new DefaultLogger(Consts.TAG);
private volatile static boolean monitorMode = false;
private volatile static boolean debuggable = false;
private volatile static boolean autoInject = false;
private volatile static _ARouter instance = null;
private volatile static boolean hasInit = false;
private volatile static ThreadPoolExecutor executor = DefaultPoolExecutor.getInstance();
private static Handler mHandler;
private static Context mContext;
private static InterceptorService interceptorService;
private _ARouter() {
}
init方法中传入了Application作为mContext和DefaultPoolExecutor实例executor
protected static synchronized boolean init(Application application) {
mContext = application;
LogisticsCenter.init(mContext, executor);
logger.info(Consts.TAG, "ARouter init success!");
hasInit = true;
mHandler = new Handler(Looper.getMainLooper());
return true;
}
先看到loadRouteMap()方法
/**
* arouter-auto-register plugin will generate code inside this method
* call this method to register all Routers, Interceptors and Providers
* @author billy.qi Contact me.
* @since 2017-12-06
*/
private static void loadRouterMap() {
registerByPlugin = false;
//auto generate register code by gradle plugin: arouter-auto-register
// looks like below:
// registerRouteRoot(new ARouter..Root..modulejava());
// registerRouteRoot(new ARouter..Root..modulekotlin());
}
可以看到Routers, Interceptors and Providers都是通过gradle脚本自动生成的
然后通过反射把这些信息加载到Warehouse类中:
for (String className : routerMap) {
if (className.startsWith(ROUTE_ROOT_PAKCAGE + DOT + SDK_NAME + SEPARATOR + SUFFIX_ROOT)) {
// This one of root elements, load root.
((IRouteRoot) (Class.forName(className).getConstructor().newInstance())).loadInto(Warehouse.groupsIndex);
} else if (className.startsWith(ROUTE_ROOT_PAKCAGE + DOT + SDK_NAME + SEPARATOR + SUFFIX_INTERCEPTORS)) {
// Load interceptorMeta
((IInterceptorGroup) (Class.forName(className).getConstructor().newInstance())).loadInto(Warehouse.interceptorsIndex);
} else if (className.startsWith(ROUTE_ROOT_PAKCAGE + DOT + SDK_NAME + SEPARATOR + SUFFIX_PROVIDERS)) {
// Load providerIndex
((IProviderGroup) (Class.forName(className).getConstructor().newInstance())).loadInto(Warehouse.providersIndex);
}
}
然后回到ARouter的init方法,只剩下一个_ARouter.afterInit()方法了
static void afterInit() {
// Trigger interceptor init, use byName.
interceptorService = (InterceptorService) ARouter.getInstance().build("/arouter/service/interceptor").navigation();
}
继续跟踪可以发现是对interceptorService 信息的一些处理。
这次先简单分析一下,
有空在研究一下InterceptorServiceImpl里的细节以及navigation中的细节、ARouter中的@AutoWired的注入也没有仔细研究。
然后判断是否GreenChannnel,不是的话会通过Gradle自动注册的InterceptorServiceImpl的doInterceptions方法拦截navigation。InterceptorServiceImpl是在ARouter.init方法中在_ARouter.init 方法中的loadRouterMap()产生的因为是gradle脚本产生的,所以发生在编译阶段。