一、interceptor
使用ARouter的拦截器的话,会生成对应的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集合中,以拦截器的优先级作为key,拦截器的class作为value。定义拦截器的时候,并不会封装成RouteMeta对象进行保存。
二、IProvider
在ARouter中,service其实也是继承自IProvider的接口,比如PathReplaceService、PretreatmentService、SerializationService等,都是继承了IProvider的。
而IProvider的实现类,会被包装成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,根据不同的Service来实现不同的操作,比如PretreatmentService预处理服务,在调用navigation的时候,就会先判断预处理服务是否为空,并且是否返回了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是否需要被替换,则是通过在调用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的调用,则是在Postcard调用withObject的时候,获取到该service,然后通过该service的object2Json和parseObject来对数据进行处理。
parseObject的调用,其实就是在针对对应的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中主动调用ARouter.getInstance().inject(this)
然后在这里会创建一个AutowiredService对象,用这个服务对象来处理ISyringe,其实就是对应的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!");
}
}
}
在这里就会调用ISyringe的inject方法,就可以对对应的Activity(其实就是传给inject方法的参数target)属性注入对应的值,这些属性不能是私有的,否则就不能直接通过对应的Activity对象直接拿到属性。
三、初始化流程解析拦截器和IProvider
1.ARouter.init(this);
在Application的onCreate方法中,调用进行初始化,其内部实现如下:
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中的各个集合的缓存内容,将每个分组、Interceptor、Provider根据分组名和模块名进行文件的分别保存。
在初始化完成之后,就会调用_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方法中,会先判断有没有设置了PathReplaceService,如果有设置了就会调用PathReplaceService.forString方法返回新的path,如果没有设置则会使用原来的path,这也就是路径替换的功能的实现。
3.Postcard.navigation
navigation有多个重载的方法,而最终都会执行_ARouter的navigation(final Context context, final Postcard postcard, final int requestCode, final NavigationCallback callback)方法,就是通过ARouter的navigation调用_ARouter的navigation方法。
public Object navigation(Context mContext, Postcard postcard, int requestCode, NavigationCallback callback) {
return _ARouter.getInstance().navigation(mContext, postcard, requestCode, callback);
}
而_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;
}
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) {
//第一次进来是拿不到RouteMeta信息的,因为routes是空的
RouteMeta routeMeta = Warehouse.routes.get(postcard.getPath());
if (null == routeMeta) {
//我们传过来的postcard的group是arouter、path是/arouter/service/interceptor
//我们在groupIndex中找对应的groupMeta,其实看到这的时候,我们默认是没有root为arouter的组,只能去arouter默认提供的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对应的IRouteGroup信息后,从map中移除掉,下次就直接从routes中去拿了
Warehouse.groupsIndex.remove(postcard.getGroup());
} catch (Exception e) {
throw new HandlerException(TAG + "Fatal exception when loading group meta. [" + e.getMessage() + "]");
}
//继续走一遍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();
//默认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();
//拿对应的provider
IProvider instance = Warehouse.providers.get(providerMeta);
if (null == instance) {
IProvider provider;
try {
//反射创建InterceptorServiceImpl
provider = providerMeta.getConstructor().newInstance();
//调用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服务转成RouteMeta,这个其实就是在alibaba:arouter-api这个库里生成的。
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进行了初始化,其实就是InterceptorServiceImpl实例。
由于InterceptorServiceImpl的type是PROVIDER,所以在completion(postcard)方法中处理完第一个if分支之后,因为把分组内容从缓存中remove了,则会执行else分支,因为type是PROVIDER的原因,所以providerMeta是InterceptorServiceImpl类型的,然后去Warehouse.providers拿,此时是空的,所以通过反射创建InterceptorServiceImpl对象,创建完调用InterceptorServiceImpl调用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();
}
}
}
});
}
在这里就会初始化拦截器,接着就会继续回到_ARouter.navigation方法中调用LogisticsCenter.completion(postcard);初始化完成RouteMeta完成之后,继续执行interceptorService.doInterceptions的调用。如下:
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;
}
在这里就会调用InterceptorServiceImpl的doInterceptions,将要执行的RouteMeta进行分发判断是否执行拦截器。
看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 {
// 调用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()) {
// 取出拦截器,并且调用拦截器的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());
// }
}
});
}
}
到这里,就可以看到对拦截器的触发。
拦截器其实是在ARouter.init()方法中调用_ARouter.afterInit()方法初始化了InterceptorService实例,然后在具体的执行路由的时候,就会调用InterceptorService实例触发拦截器的执行。