Arouter是什么及其注解处理器的原理在文章:Arouter之注解器处理器原理解析中有说明,建议先去看这篇文章,因为API原理解析依赖注解处理器生成的:路由表类文件、依赖注入辅助工具类文件、拦截器表类文件。
Arouter
Arouter类是Arouter框架的门面类,暴露接口给开发者调用,其所有方法都是调用_Arouter对应的方法。
我看下几个下几个常用的方法的源码:
public final class ARouter {
private volatile static ARouter instance = null;
public static void init(Application application) {
//初始化Arouter,其内部调用的是_Arouter进行初始化
if (!hasInit) {
logger = _ARouter.logger;
_ARouter.logger.info(Consts.TAG, "ARouter init start.");
//调用的是_Arouter进行初始化
hasInit = _ARouter.init(application);
if (hasInit) {
//初始化成功,调用_Arouter的afterInit方法
_ARouter.afterInit();
}
_ARouter.logger.info(Consts.TAG, "ARouter init over.");
}
}
public static ARouter getInstance() {
//获取Arouter单例
if (!hasInit) {
//未初始化,则抛出异常
throw new InitException("ARouter::Init::Invoke init(context) first!");
} else {
//已初始化,则创建Arouter单例
if (instance == null) {
synchronized (ARouter.class) {
if (instance == null) {
instance = new ARouter();
}
}
}
return instance;
}
}
public void inject(Object thiz) {
//调用_ARouter的注入方法
_ARouter.inject(thiz);
}
public Postcard build(String path) {
//调用_ARouter单例通过路由路径构建路由明信片Postcard
return _ARouter.getInstance().build(path);
}
public Postcard build(Uri url) {
//调用_ARouter单例通过路由url构建路由明信片Postcard
return _ARouter.getInstance().build(url);
}
public T navigation(Class extends T> service) {
//调用_ARouter单例通过服务Class导航到具体的服务,并返回服务对象
return _ARouter.getInstance().navigation(service);
}
public Object navigation(Context mContext, Postcard postcard, int requestCode, NavigationCallback callback) {
//调用_ARouter单例通过路由明信片导航到具体的路由,requestCode是startActivityForResult的requestCode
return _ARouter.getInstance().navigation(mContext, postcard, requestCode, callback);
}
}
根据Arouter的核心源码部分,我们得出如下结论:
1、使用Arouter之前,必须先进行初始化,否则会抛出未初始化的异常
2、Arouter的是作为_Arouter的门面,内部调用的是_Arouter对应的方法
Arouter初始化
Arouter的初始哈的真实实现是在_Arouter的init方法:
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;
}
_Arouter的初始化接着调用LogisticsCenter的初始化方法:
public synchronized static void init(Context context, ThreadPoolExecutor tpe) throws HandlerException {
mContext = context;
executor = tpe;
try {
long startInit = System.currentTimeMillis();
//load by plugin first
loadRouterMap();
if (registerByPlugin) {
//如果使用了自动注册插件,则啥也不做
logger.info(TAG, "Load router map by arouter-auto-register plugin.");
} else {
//如果没有使用自动注册插件,则需要完成RoutGroup、Provider、Interceptor的注册
//路由文件集合(包括:RouteRoot、Provider、Interceptor),值为类全限定名
Set routerMap;
// It will rebuild router map every times when debuggable.
if (ARouter.debuggable() || PackageUtils.isNewVersion(context)) {
//当前应用是新版本,重新从apk的dex中读取路由文件集合
logger.info(TAG, "Run with debug mode or new install, rebuild router map.");
// These class was generated by arouter-compiler.
//从apk的dex中读取所有的路由文件集合
routerMap = ClassUtils.getFileNameByPackageName(mContext, ROUTE_ROOT_PAKCAGE);
if (!routerMap.isEmpty()) {
//路由文件集合不为空,则将路由文件集合缓存到SharedPreferences中
context.getSharedPreferences(AROUTER_SP_CACHE_KEY, Context.MODE_PRIVATE).edit().putStringSet(AROUTER_SP_KEY_MAP, routerMap).apply();
}
//更新缓存中路由文件集合的版本
PackageUtils.updateVersion(context); // Save new version name when router map update finishes.
} else {
//当前应用不是新版本,从缓存中读取路由文件集合
logger.info(TAG, "Load router map from cache.");
routerMap = new HashSet<>(context.getSharedPreferences(AROUTER_SP_CACHE_KEY, Context.MODE_PRIVATE).getStringSet(AROUTER_SP_KEY_MAP, new HashSet()));
}
logger.info(TAG, "Find router map finished, map size = " + routerMap.size() + ", cost " + (System.currentTimeMillis() - startInit) + " ms.");
startInit = System.currentTimeMillis();
for (String className : routerMap) {
//遍历路由文件集合
if (className.startsWith(ROUTE_ROOT_PAKCAGE + DOT + SDK_NAME + SEPARATOR + SUFFIX_ROOT)) {
// This one of root elements, load root.
//如果路由文件类型为RouteRoot类型,反射创建RouteRoot对象,并调用其loadInto方法将路由组加载到全局路由组表Warehouse.groupsIndex中
((IRouteRoot) (Class.forName(className).getConstructor().newInstance())).loadInto(Warehouse.groupsIndex);
} else if (className.startsWith(ROUTE_ROOT_PAKCAGE + DOT + SDK_NAME + SEPARATOR + SUFFIX_INTERCEPTORS)) {
//如果路由文件类型为Interceptor类型,反射创建Interceptor对象,并调用其loadInto方法将拦截器加载到全局拦截器表Warehouse.interceptorsIndex中
// 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
//如果路由文件类型为Provider类型,反射创建Provider对象,并调用其loadInto方法将provider加载到全局服务表Warehouse.providersIndex中
((IProviderGroup) (Class.forName(className).getConstructor().newInstance())).loadInto(Warehouse.providersIndex);
}
}
}
//.....
} catch (Exception e) {
//.....
}
}
根据上述源码的解析,我们可以得出以下结论:
1、Arouter的初始化最终进入LogisticsCenter的init方法实现初始化
2、初始化的工作主要是:
- 设置全局context
- 如果没有使用自动注册插件,那么就是将注解器生成的路由组RouteRoot文件、拦截器文件InterceptorGroup、服务Provider注册到全局变量中,全局变量分别是:
- Warehouse.groupsIndex:路由组表,key是组名,value是路由组RouteGroup的Class
- Warehouse.interceptorsIndex:拦截器列表,key是拦截器优先级,value是拦截器InterceptorGroup的class
- Warehouse.providersIndex:服务表,key是服务器类全限定名,value是描述服务的路由元RouteMeta对象
Arouter导航
Arouter的导航可以实现:打开指定路由的Activity、获取指定路由的Fragment/ContentProvider/Boardcast、获取指定路由的Provider。导航的方式分为
- 根据路由路径path进行导航
- 根据uri进行导航
- 根据服务的class进行导航
路径导航
我们先看通过路径进行导航的源码流程:
Arouter的build(path)和build(path, group)都会进入_Arouter对应的方法,我们直接看_Arouter对应的方法:
protected Postcard build(String path) {
if (TextUtils.isEmpty(path)) {
throw new HandlerException(Consts.TAG + "Parameter is invalid!");
} else {
//这一步主要主要是路由重定向,就是把path转换为其它的路由路径
PathReplaceService pService = ARouter.getInstance().navigation(PathReplaceService.class);
if (null != pService) {
path = pService.forString(path);
}
//第二个参数extractGroup取paht的第一段//作为组名
//第三个参数表示是经过重定向的
return build(path, extractGroup(path), true);
}
}
protected Postcard build(String path, String group, Boolean afterReplace) {
//构建路由明信片Postcard
if (TextUtils.isEmpty(path) || TextUtils.isEmpty(group)) {
//路由路径或者路由组为空,抛出异常
throw new HandlerException(Consts.TAG + "Parameter is invalid!");
} else {
if (!afterReplace) {
//如果没有经过重定向,则进行重定向
PathReplaceService pService = ARouter.getInstance().navigation(PathReplaceService.class);
if (null != pService) {
path = pService.forString(path);
}
}
//通过路由路径和组名创建路由明信片Postcard
return new Postcard(path, group);
}
}
构建出路由明信片Postcard之后,调用Postcard的导航方法navigation继续完成导航:
public Object navigation(Context context) {
return navigation(context, null);
}
public Object navigation(Context context, NavigationCallback callback) {
return ARouter.getInstance().navigation(context, this, -1, callback);
}
public void navigation(Activity mContext, int requestCode) {
navigation(mContext, requestCode, null);
}
public void navigation(Activity mContext, int requestCode, NavigationCallback callback) {
ARouter.getInstance().navigation(mContext, this, requestCode, callback);
}
最终调用_Arouter的navigation(mContext, postcard, requestCode, callback)方法:
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;
}
// Set context to postcard.
//明信片设置上下文context
postcard.setContext(null == context ? mContext : context);
try {
//构建路由明信片的完整信息,如路由具体信息、路由需要依赖注入的参数等
LogisticsCenter.completion(postcard);
} catch (NoRouteFoundException ex) {
//......
//导航失败
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继续完成路由导航
_navigation(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 {
//绿色通道,直接调用_navigation继续完成路由导航
return _navigation(postcard, requestCode, callback);
}
return null;
}
我们先看LogisticsCenter怎么完善明信片的信息:
public synchronized static void completion(Postcard postcard) {
//.....
//根据路由路径,从路由表中获取路由信息
RouteMeta routeMeta = Warehouse.routes.get(postcard.getPath());
if (null == routeMeta) {
//未加载路由
// Maybe its does't exist, or didn't load.
if (!Warehouse.groupsIndex.containsKey(postcard.getGroup())) {
//如果路由组中没有匹配的路由,则抛出异常
throw new NoRouteFoundException(TAG + "There is no route match the path [" + postcard.getPath() + "], in group [" + postcard.getGroup() + "]");
} else {
// Load route and cache it into memory, then delete from metas.
try {
//......
//动态的将路由组中路由都加载到路由表中
addRouteGroupDynamic(postcard.getGroup(), null);
//......
} catch (Exception e) {
throw new HandlerException(TAG + "Fatal exception when loading group meta. [" + e.getMessage() + "]");
}
//加载完路由,重新调用completion完善路由明信片
completion(postcard); // Reload
}
} else {
//已加载路由
//设置路由class
postcard.setDestination(routeMeta.getDestination());
//设置路由类型
postcard.setType(routeMeta.getType());
//设置路由优先级
postcard.setPriority(routeMeta.getPriority());
//设置路由附加信息
postcard.setExtra(routeMeta.getExtra());
Uri rawUri = postcard.getUri();
if (null != rawUri) { // Try to set params into bundle.
//如果通过Uri导航,则将uri中的query转为bundle参数值列表
Map resultMap = TextUtils.splitQueryParameters(rawUri);
//路由需要依赖注入的参数类型列表
Map paramsType = routeMeta.getParamsType();
if (MapUtils.isNotEmpty(paramsType)) {
// Set value by its type, just for params which annotation by @Param
//根据需要依赖注入的参数类型列表构建出传递给路由的参数值Bundle
for (Map.Entry 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
//将uri也作为参数值也传给路由
postcard.withString(ARouter.RAW_URI, rawUri.toString());
}
switch (routeMeta.getType()) {
case PROVIDER: // if the route is provider, should find its instance
// Its provider, so it must implement IProvider
//如果路由类型是Provider类型,则:
//反射创建服务实现类,并放入全局服务表Warehouse.providers中
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
provider.init(mContext);
//将provider放入全球服务表Warehouse.providers中
Warehouse.providers.put(providerMeta, provider);
instance = provider;
} catch (Exception e) {
logger.error(TAG, "Init provider failed!", e);
throw new HandlerException("Init provider failed!");
}
}
//设置路由明信片的服务提供者
postcard.setProvider(instance);
//所有的provider都不需要拦截,直接设置为绿色通道
postcard.greenChannel(); // Provider should skip all of interceptors
break;
case FRAGMENT:
//所有的fragment不需要拦截,直接设置为绿色通道
postcard.greenChannel(); // Fragment needn't interceptors
default:
break;
}
}
}
public synchronized static void addRouteGroupDynamic(String groupName, IRouteGroup group) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
//动态加载路由组,将路由组内的路由加入全局路由表Warehouse.routes中
if (Warehouse.groupsIndex.containsKey(groupName)){\
//如果存在路由组RouteGroup,则:
// If this group is included, but it has not been loaded
// load this group first, because dynamic route has high priority.
//从全局路由组表Warehouse.groupsIndex中获取路由组的class,通过反射创建路由组对象,并调用loadInto方法将组内的路由将入全局路由表Warehouse.routes中
Warehouse.groupsIndex.get(groupName).getConstructor().newInstance().loadInto(Warehouse.routes);
Warehouse.groupsIndex.remove(groupName);
}
// cover old group.
if (null != group) {
group.loadInto(Warehouse.routes);
}
}
LogisticsCenter的completion是通过从全局路由组表反射Warehouse.groupsIndex中的路由组RouteGroup对象,并调用RouteGroup对象的loadInto将组内路由加入全局路由表Warehouse.routes,接着从路由表中获取路由元对象RouteMeta的信息来填充完善路由明信片postcard对象,包括目标路由的class、目标路由需要注入的参数列表及其参数值、目标provider等。
我们接着来分析上面导航时没有被拦截,需要继续完成导航的_Arouter的_navigation的源码:
private Object _navigation(final Postcard postcard, final int requestCode, final NavigationCallback callback) {
//获取上下文context:activity或者applicationcontext
final Context currentContext = postcard.getContext();
switch (postcard.getType()) {
case ACTIVITY:
// Build intent
//如果目标路由是activity,则:
//创建activity的意图intent,class是路由名片中目标路由activity的class
final Intent intent = new Intent(currentContext, postcard.getDestination());
//设置意图的参数,即需要依赖注入的字段列表及其参数值
intent.putExtras(postcard.getExtras());
// Set flags.
//设置意图标志位
int flags = postcard.getFlags();
if (0 != flags) {
intent.setFlags(flags);
}
// Non activity, need FLAG_ACTIVITY_NEW_TASK
if (!(currentContext instanceof Activity)) {
//如果上下文不是activity,则需要在新的栈中打开activity
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
}
// Set Actions
//设置intent的action
String action = postcard.getAction();
if (!TextUtils.isEmpty(action)) {
intent.setAction(action);
}
// Navigation in main looper.
runInMainThread(new Runnable() {
@Override
public void run() {
//回到主线程打开activity
startActivity(requestCode, currentContext, intent, postcard, callback);
}
});
break;
case PROVIDER:
//如果目标路由是provider类型,则:
//直接返回目标路由提供的服务对象
return postcard.getProvider();
case BOARDCAST:
case CONTENT_PROVIDER:
case FRAGMENT:
//如果目标路由是fragment/contentProvider/Boardcast,则:
//获取目标路由的class
Class> fragmentMeta = postcard.getDestination();
try {
//通过class反射目标路由对象
Object instance = fragmentMeta.getConstructor().newInstance();
if (instance instanceof Fragment) {
//如果是fragment,则设置参数及其参数值
((Fragment) instance).setArguments(postcard.getExtras());
} else if (instance instanceof android.support.v4.app.Fragment) {
//如果是fragment,则设置参数及其参数值
((android.support.v4.app.Fragment) instance).setArguments(postcard.getExtras());
}
//返回目标路由对象
return instance;
} catch (Exception ex) {
logger.error(Consts.TAG, "Fetch fragment instance error, " + TextUtils.formatStackTrace(ex.getStackTrace()));
}
case METHOD:
case SERVICE:
default:
return null;
}
return null;
}
到此完成整改路由导航的流程。
Uri导航
我们接着看通过uri导航的源码流程:
Arouter的build(Uri uri)会进入_Arouter对应的方法,我们直接看_Arouter对应的方法:
protected Postcard build(Uri uri) {
if (null == uri || TextUtils.isEmpty(uri.toString())) {
//无效的uri抛出异常
throw new HandlerException(Consts.TAG + "Parameter invalid!");
} else {
//路由重定向
PathReplaceService pService = ARouter.getInstance().navigation(PathReplaceService.class);
if (null != pService) {
uri = pService.forUri(uri);
}
//从uri中取出路由路径path,使用路由路径的第一段//中的字符串作为路由组名,使用path和组名创建路由明信片
return new Postcard(uri.getPath(), extractGroup(uri.getPath()), uri, null);
}
}
uri导航的方式是从uri中路由路径path,使用路由路径的第一段//中的字符串作为路由组名,使用path和组名创建路由明信片。创建出路由明信片之后,接下来的导航流程与上面分析的“路径导航”一样,在此不做重复介绍。
Class导航
我们接着看通过Class导航的流程,class导航方式只能导航到模块提供的服务,且会返回class对应的服务对象,直接使用的是navigation方法,我们来看看navigation(Class extends T> service)的源码流程:
protected 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;
}
// Set application to postcard.
//找到路由,设置路由明信片的上下文
postcard.setContext(mContext);
//完善路由明信片
LogisticsCenter.completion(postcard);
//直接返回路由明信片中的服务对象
return (T) postcard.getProvider();
} catch (NoRouteFoundException ex) {
logger.warning(Consts.TAG, ex.getMessage());
return null;
}
}
//LogisticsCenter.buildProvider
public static Postcard buildProvider(String serviceName) {
//根据服务类名从全局服务表Warehouse.providersIndex中取出服务对应的路由元信息对象meta
RouteMeta meta = Warehouse.providersIndex.get(serviceName);
if (null == meta) {
//找不到服务,返回空
return null;
} else {
//找到服务,则通过路由元信息中的路由路径和组名创建路由明信片并返回
return new Postcard(meta.getPath(), meta.getGroup());
}
}
通过class进行导航是为获取模块提供的服务服务的,它先根据服务类名从全局服务表Warehouse.providersIndex中取出服务对应的路由元信息对象,使用此路由元信息创建对应的路由明信片对象,接着调用LogisticsCenter.completion完善路由明信片,完善的逻辑在上面的“路由导航”有分析过,在此不做重复介绍,接着返回明信片中的服务对象,完成本次导航。
导航拦截
在上面的路由导航分析中,在导航时有介绍到使用了拦截器对导航进行拦截处理,我们来看看拦截器的工作原理:
首先呢,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 (MapUtils.isNotEmpty(Warehouse.interceptorsIndex)) {
//如果拦截表不为空,则:
//等待拦截器调度中心完成初始化
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((Throwable) postcard.getTag());
} 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 execute over with fatal exception.
//被拦截器拦截,并结束拦截流程
postcard.setTag(null == exception ? new HandlerException("No message.") : exception); // 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) {
//初始化拦截器调度中心服务,是在_Arouter的afterinit中最终调用LogisticsCenter.completion调用的
LogisticsCenter.executor.execute(new Runnable() {
@Override
public void run() {
if (MapUtils.isNotEmpty(Warehouse.interceptorsIndex)) {
for (Map.Entry> entry : Warehouse.interceptorsIndex.entrySet()) {
//遍历拦截器class列表
Class extends IInterceptor> interceptorClass = entry.getValue();
try {
//根据class反射创建拦截器
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依赖注入
我们接着分析依赖注入的源码流程:
static void inject(Object thiz) {
//获取Arouter内置的依赖注入服务类
AutowiredService autowiredService = ((AutowiredService) ARouter.getInstance().build("/arouter/service/autowired").navigation());
if (null != autowiredService) {
//调用autowire实现自动注入
autowiredService.autowire(thiz);
}
}
Arouter内置了依赖注入服务类AutowiredServiceImpl,我们接着来分析AutowiredServiceImpl:
@Route(path = "/arouter/service/autowired")
public class AutowiredServiceImpl implements AutowiredService {
//lrucache:最近最少使用的依赖注入类
private LruCache classCache;
//黑名单列表
private List blackList;
@Override
public void init(Context context) {
//设置最近最少使用LruCache最大容量为50,即最大缓存50个依赖注入类
classCache = new LruCache<>(50);
blackList = new ArrayList<>();
}
@Override
public void autowire(Object instance) {
//主动注入
//调用doInject完成自动注入
doInject(instance, null);
}
/**
* Recursive injection
*
* @param instance who call me.
* @param parent parent of me.
*/
private void doInject(Object instance, Class> parent) {
//parant是需要注入的类
Class> clazz = null == parent ? instance.getClass() : parent;
//根据类名获取注射器
ISyringe syringe = getSyringe(clazz);
if (null != syringe) {
//如果注射器不为空,则调用注射器的inject方法,完成对目标类instance中需要依赖注入的字段进行注入赋值
syringe.inject(instance);
}
//获取目标类的父类
Class> superClazz = clazz.getSuperclass();
// has parent and its not the class of framework.
if (null != superClazz && !superClazz.getName().startsWith("android")) {
//继续对目标类的父类完成依赖注入
doInject(instance, superClazz);
}
}
private ISyringe getSyringe(Class> clazz) {
String className = clazz.getName();
try {
if (!blackList.contains(className)) {
//黑名单不含此注射器,则:
//从缓存区注射器
ISyringe syringeHelper = classCache.get(className);
if (null == syringeHelper) { // No cache.
//如果缓存中不存在注册器,则:
//通过类名反射创建注射器对象
syringeHelper = (ISyringe) Class.forName(clazz.getName() + SUFFIX_AUTOWIRED).getConstructor().newInstance();
}
//将注射器将入缓存中
classCache.put(className, syringeHelper);
//返回注射器
return syringeHelper;
}
} catch (Exception e) {
//获取注射器异常,则加入黑名单
blackList.add(className); // This instance need not autowired.
}
return null;
}
}
结合上述源码的分析,我们对Arouter可以做如下概括:
1、对Arouter初始化时,如果没有使用自动注册插件,则需要执行以下的注册操作:
- 从apk的dex文件中找出所有的路由组文件RouteRoot、服务类文件Provider、拦截器文件
- 反射创建这些类,并调用他们的loadInto方法:将路由组放入全局路由组表Warehouse.groupsIndex中、将拦截器放入全局拦截器索引表中、Warehouse.interceptorsIndex中、将服务路由信息放入全局服务索引表Warehouse.providersIndex中。
2、初始化完成后,导航到拦截器调度中心服务,并完成拦截器调度中心服务的初始化
3、导航时根据路由路径、路由组生成路由明信片对象,接着调用LogisticsCenter的completion完善路由明信片的信息:
- 反射创建路由组对象RouteRoot,调用RouteRoot的loadInto方法,将组内的路由都缓存到全局的路由表Warehouse.routes中
- 从全局路由表Warehouse.routes中获取路由元信息,并设置路由明信片的目标路由class、需要注入的字段列表及其参数值、如果是服务则设置服务并进行初始化
4、非绿色通道需要调用拦截器调度中心,调度所有的拦截器进行处理,如果不拦截则最终调用最后的导航步骤6
5、绿色通道直接进入最终的导航步骤6
6、最后的导航步骤
- 如果是activity,使用明信片的信息构建目标activity的intent、参数列表、标志位等。进入目标activity之后,如果需要依赖注入,则调用inject方法调用对应的注入辅助类完成对字段的注入赋值
- 如果是fragment,反射创建fragment,并使用明信片的信息设置参数列表,并返回fragment。进入目标fragment之后,如果需要依赖注入,则调用inject方法调用对应的注入辅助类完成对字段的注入赋值
- 如果是provider,直接返回明信片中的provider
- 如果是contentprovider或者boardcast,反射创建contentprovider或者boardcast,然后返回contentprovider或者boardcast