ARouter源码解析
1-初始化
ARouter.init()开始,init方法的主要工作就是ARouter实例化,_ARouter的初始化。_ARouter是具体实现类。这里用到了外观模式,将所有API通过ARouter暴露,具体实现则交由_ARouter
//ARouter.java
public static void init(Application application) {
if (!hasInit) {
//日志类
logger = _ARouter.logger;
_ARouter.logger.info(Consts.TAG, "ARouter init start.");
//@1._ARouter初始化
hasInit = _ARouter.init(application);
if (hasInit) {
//@4.通过路由开启Service,预解析拦截器
_ARouter.afterInit();
}
_ARouter.logger.info(Consts.TAG, "ARouter init over.");
}
}
@1._ARouter的初始化:
protected static synchronized boolean init(Application application) {
mContext = application;
//@2.LogisticsCenter初始化
LogisticsCenter.init(mContext, executor);
logger.info(Consts.TAG, "ARouter init success!");
hasInit = true;
//主线程Looper创建一个Handler
mHandler = new Handler(Looper.getMainLooper());
return true;
}
@2.LogisticsCenter初始化。主要工作就是初始化所有类的map。在编译期通过gradle插件(arouter-compiler)扫描文件,生成路由映射文件,apt生成路由映射关系文件。
public synchronized static void init(Context context, ThreadPoolExecutor tpe) throws HandlerException {
mContext = context;
executor = tpe;
try {
。。。
if (registerByPlugin) {
。。。
} else {
Set<String> routerMap;
//debuggable模式或版本更新,重新获取routerMap映射表
if (ARouter.debuggable() || PackageUtils.isNewVersion(context)) {
logger.info(TAG, "Run with debug mode or new install, rebuild router map.");
// These class was generated by arouter-compiler.
//遍历arouter-compiler生成的包名下所有文件,读取routerMap路由映射表,将routerMap存储在sp中
routerMap = ClassUtils.getFileNameByPackageName(mContext, ROUTE_ROOT_PAKCAGE);
if (!routerMap.isEmpty()) {
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 {
//直接从sp中读取routerMap。set<String>类型,存储的是className
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<String>()));
}
logger.info(TAG, "Find router map finished, map size = " + routerMap.size() + ", cost " + (System.currentTimeMillis() - startInit) + " ms.");
startInit = System.currentTimeMillis();
//@3.遍历routerMap,根据文件类型存储到Warehouse对应的字段。通过反射实例化对象,调用loadInto实现。
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);
}
}
}
logger.info(TAG, "Load root element finished, cost " + (System.currentTimeMillis() - startInit) + " ms.");
if (Warehouse.groupsIndex.size() == 0) {
logger.error(TAG, "No mapping files were found, check your configuration please!");
}
if (ARouter.debuggable()) {
logger.debug(TAG, String.format(Locale.getDefault(), "LogisticsCenter has already been loaded, GroupIndex[%d], InterceptorIndex[%d], ProviderIndex[%d]", Warehouse.groupsIndex.size(), Warehouse.interceptorsIndex.size(), Warehouse.providersIndex.size()));
}
} catch (Exception e) {
throw new HandlerException(TAG + "ARouter init logistics center exception! [" + e.getMessage() + "]");
}
}
@3.这里存储到Warehose里的主要是三个HashMap,分别是groupsIndex、interceptorsIndex、providersIndex
- interceptorsIndex-TreeMap实现,根据拦截器的优先级自平衡的有序结构,红黑树实现。key是优先级,value是拦截器类名
- groupsIndex-key是路由的group,value是该group下的路由映射关系类
- providersIndex-
存储过程是通过routerMap拿到className,反射生成实例调用其loadInto方法,该方法是APT在@Route注解的类中自动生成的代码
public class ARouter$$Root$$app implements IRouteRoot {
@Override
public void loadInto(Map<String, Class<? extends IRouteGroup>> routes) {
//key为分组名,即路径的第一段,value为分组中所有的映射关系
routes.put("service", ARouter$$Group$$service.class);
routes.put("test", ARouter$$Group$$test.class);
}
}
//将module中使用@Route注解的activity或Fragment添加到集合中,这里的方法会在之后调用
public class ARouter$$Group$$test implements IRouteGroup {
@Override
public void loadInto(Map<String, RouteMeta> atlas) {
atlas.put("/test/activity1", RouteMeta.build(RouteType.ACTIVITY, Test1Activity.class, "/test/activity1", "test", new java.util.HashMap<String, Integer>(){{put("pac", 9); put("ch", 5); put("fl", 6); put("obj", 10); put("name", 8); put("dou", 7); put("boy", 0); put("objList", 10); put("map", 10); put("age", 3); put("url", 8); put("height", 3); }}, -1, -2147483648));
atlas.put("/test/activity2", RouteMeta.build(RouteType.ACTIVITY, Test2Activity.class, "/test/activity2", "test", new java.util.HashMap<String, Integer>(){{put("key1", 8); }}, -1, -2147483648));
atlas.put("/test/activity3", RouteMeta.build(RouteType.ACTIVITY, Test3Activity.class, "/test/activity3", "test", new java.util.HashMap<String, Integer>(){{put("name", 8); put("boy", 0); put("age", 3); }}, -1, -2147483648));
atlas.put("/test/activity4", RouteMeta.build(RouteType.ACTIVITY, Test4Activity.class, "/test/activity4", "test", null, -1, -2147483648));
atlas.put("/test/fragment", RouteMeta.build(RouteType.FRAGMENT, BlankFragment.class, "/test/fragment", "test", null, -1, -2147483648));
atlas.put("/test/webview", RouteMeta.build(RouteType.ACTIVITY, TestWebview.class, "/test/webview", "test", null, -1, -2147483648));
}
}
@4._ARouter.afterInit()方法。通过ARouter获取管理拦截器的Service的实例,并开启服务进行拦截器的一些初始化工作。
static void afterInit() {
// Trigger interceptor init, use byName.
interceptorService = (InterceptorService) ARouter.getInstance().build("/arouter/service/interceptor").navigation();
}
InterceptorServiceImpl服务主要是实例化拦截器,并将实例添加到Warehose的interceptors中
@Route(path = "/arouter/service/interceptor")
public class InterceptorServiceImpl implements InterceptorService {
private static boolean interceptorHasInit;
private static final Object interceptorInitLock = new Object();
@Override
public void init(final Context context) {
... //省略子线程以及同步处理,下面的操作实际是在子线程处理的
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() + "]");
}
}
...
}
}
总结初始化过程:
- (1)ARouter.init()-->_ARouter.init()-->LogisticsCenter.init()
- (2)debuggable()模式或新版本,则从指定的router-compiler生成的目录遍历文件加载路由映射表routerMap,并缓存到SP;否则直接读取SP中的routerMap
- (3)遍历routerMap,根据className的类型依次初始化并存储到内存中。Warehose对应的三个map。groupsIndex(gourp名-该分组下的所有映射关系类名)、interceptorsIndex(优先级-拦截器名)、providersIndex()
-
(4)_ARouter.afterInit().通过路由打开InterceptorService,遍历Warehose中的interceptorsIndex,实例化对象并存储到Warehose.interceptors
图1-初始化流程
2-路由跳转
跳转的代码从ARouter.getInstance()-->ARouter.build()
ARouter.getInstance().build("/test/activity").navigation();
ARouter.build()-->_ARouter.getInstance().build()
protected Postcard build(String path) {
if (TextUtils.isEmpty(path)) {
throw new HandlerException(Consts.TAG + "Parameter is invalid!");
} else {
//PathReplaceService是实现路径动态变化,也就是重定向功能。
PathReplaceService pService = ARouter.getInstance().navigation(PathReplaceService.class);
if (null != pService) {
//拿到通过PathReplaceService修改后的path
path = pService.forString(path);
}
//@1.extractGroup(path)解析出group名
return build(path, extractGroup(path));
}
}
@1._ARouter.build方法。返回一个Postcard对象用于存储跳转信息。Postcard继承RouteMeta,封装了路由类型、@Autowired属性集合Map(属性名-属性类型)等信息
protected Postcard build(String path, String group) {
if (TextUtils.isEmpty(path) || TextUtils.isEmpty(group)) {
throw new HandlerException(Consts.TAG + "Parameter is invalid!");
} else {
PathReplaceService pService = ARouter.getInstance().navigation(PathReplaceService.class);
if (null != pService) {
path = pService.forString(path);
}
return new Postcard(path, group);
}
}
然后调用_ARouter.navigation方法
protected Object navigation(final Context context, final Postcard postcard, final int requestCode, final NavigationCallback callback) {
。。。
try {
//@2.查找对应的路由信息
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) {
//调用onLost回调
callback.onLost(postcard);
} else {
// 或者调用DegradeService全局降级的onLost处理
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()) { // 需要拦截处理
//@3.调用InterceptorService拦截
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);
}
logger.info(Consts.TAG, "Navigation failed, termination by interceptor : " + exception.getMessage());
}
});
} else {//不需要拦截处理
//@3.最终跳转
return _navigation(context, postcard, requestCode, callback);
}
return null;
}
@2.LogisticsCenter.completion方法。主要工作就是从Warehouse中懒加载路由信息并缓存到Postcard,包括@Autowired注解的参数列表封装到Postecard的mBundle中
public synchronized static void completion(Postcard postcard) {
if (null == postcard) {
throw new NoRouteFoundException(TAG + "No postcard!");
}
RouteMeta routeMeta = Warehouse.routes.get(postcard.getPath());
if (null == routeMeta) { // Maybe its does't exist, or didn't load.
Class<? extends IRouteGroup> groupMeta = Warehouse.groupsIndex.get(postcard.getGroup()); // Load route meta.
if (null == groupMeta) {
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 {
if (ARouter.debuggable()) {
logger.debug(TAG, String.format(Locale.getDefault(), "The group [%s] starts loading, trigger by [%s]", postcard.getGroup(), postcard.getPath()));
}
//从Warehouse.groupIndex读取到对应的映射列表。并将列表中的路由加到Warehouse.routes
//同时已加载的group从groupIndex中移除
IRouteGroup iGroupInstance = groupMeta.getConstructor().newInstance();
iGroupInstance.loadInto(Warehouse.routes);
Warehouse.groupsIndex.remove(postcard.getGroup());
if (ARouter.debuggable()) {
logger.debug(TAG, String.format(Locale.getDefault(), "The group [%s] has already been loaded, trigger by [%s]", postcard.getGroup(), postcard.getPath()));
}
} catch (Exception e) {
throw new HandlerException(TAG + "Fatal exception when loading group meta. [" + e.getMessage() + "]");
}
//再次加载
completion(postcard); // Reload
}
} else {
//将路由参数存储到Postcard
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.
Map<String, String> resultMap = TextUtils.splitQueryParameters(rawUri);
Map<String, Integer> paramsType = routeMeta.getParamsType();
if (MapUtils.isNotEmpty(paramsType)) {
// Set value by its type, just for params which annotation by @Param
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()) {
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;
}
}
}
@3.跳转_navigation
- Activity。则构建Intent,将相关信息封装到Intent,包括action、bundle等。在主线程调用startActivity跳转。
- Fragment。创建Fragment实例,设置bundle参数,返回该Fragment实例
private Object _navigation(final Context context, final Postcard postcard, final int requestCode, final NavigationCallback callback) {
final Context currentContext = null == context ? mContext : context;
switch (postcard.getType()) {
case ACTIVITY:
// 构建intent
final Intent intent = new Intent(currentContext, postcard.getDestination());
intent.putExtras(postcard.getExtras());
// 设置Activity启动模式
int flags = postcard.getFlags();
if (-1 != flags) {
intent.setFlags(flags);
} else if (!(currentContext instanceof Activity)) { // Non activity, need less one flag.
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
}
// 设置Actions
String action = postcard.getAction();
if (!TextUtils.isEmpty(action)) {
intent.setAction(action);
}
// 主线程调用startActivity跳转
runInMainThread(new Runnable() {
@Override
public void run() {
startActivity(requestCode, currentContext, intent, postcard, callback);
}
});
break;
case PROVIDER:
return postcard.getProvider();
case BOARDCAST:
case CONTENT_PROVIDER:
case FRAGMENT:
Class fragmentMeta = postcard.getDestination();
try {
//生成fragment实例
Object instance = fragmentMeta.getConstructor().newInstance();
//设置bundle参数
if (instance instanceof Fragment) {
((Fragment) instance).setArguments(postcard.getExtras());
} else if (instance instanceof android.support.v4.app.Fragment) {
((android.support.v4.app.Fragment) instance).setArguments(postcard.getExtras());
}
//返回fragment实例
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;
}
跳转过程总结:封装Postcard -> 查找信息集合,实例化目标类 -> 返回实例或者跳转。
- (1)ARouter.getInstance().build()-->_ARouter.getInstance().build()
- (2)PathReplaceService执行path重定向
- (3)_ARouter.navigation-->LogisticsCenter.completion。
- (4)Warehouse的routes中取路由参数,获取失败则解析groupsIndex中对应group的路由列表,添加到routes中。
- (5)添加完毕再次从routes获取,将路由参数封装到Poster并返回
- (6)启动InterceptorService执行拦截器
-
(7)执行_navigation。若是Activity,则将poster信息封装到Intent,通过在主线程startActivity跳转。若是Fragment,根据poster信息创建Fragment实例并返回
图2-跳转流程
3-@Interceptor拦截
@4.InterceptorService的doInterceptions进行拦截处理。通过CountDownLatch实现计数阻塞。计数初始值为拦截器个数,每执行一个拦截器操作计数-1。计数为0或timeout则取消线程阻塞
@Override
public void doInterceptions(final Postcard postcard, final InterceptorCallback callback) {
if (null != Warehouse.interceptors && Warehouse.interceptors.size() > 0) {
... //省略同步等待初始化
LogisticsCenter.executor.execute(new Runnable() {
@Override
public void run() {
//拦截器个数作为计数初始值
CancelableCountDownLatch interceptorCounter = new CancelableCountDownLatch(Warehouse.interceptors.size());
try {
_excute(0, interceptorCounter, postcard);
//阻塞线程直到超时,或者计数归0
interceptorCounter.await(postcard.getTimeout(), TimeUnit.SECONDS);
if (interceptorCounter.getCount() > 0) { //拦截超时
callback.onInterrupt(new HandlerException("The interceptor processing timed out."));
} else if (null != postcard.getTag()) { // 被拦截
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) {
// 如果放行,则计数减1,执行后一个拦截器
counter.countDown();
_excute(index + 1, counter, postcard);
}
@Override
public void onInterrupt(Throwable exception) {
// 拦截,将exception存入postcard的tag字段,计数归零
postcard.setTag(null == exception ? new HandlerException("No message.") : exception.getMessage());
counter.cancel();
});
}
}
4-@Autowired参数注解
@Route(path = "/arouter/service/autowired")
public class AutowiredServiceImpl implements AutowiredService {
private LruCache<String, ISyringe> classCache;
private List<String> blackList;
@Override
public void init(Context context) {
classCache = new LruCache<>(66);
blackList = new ArrayList<>();
}
@Override
public void autowire(Object instance) {
String className = instance.getClass().getName();
try {
if (!blackList.contains(className)) {
ISyringe autowiredHelper = classCache.get(className);
if (null == autowiredHelper) { // No cache.
autowiredHelper = (ISyringe) Class.forName(instance.getClass().getName() + SUFFIX_AUTOWIRED).getConstructor().newInstance();
}
//从mBundle中取出参数赋值
autowiredHelper.inject(instance);
classCache.put(className, autowiredHelper);
}
} catch (Exception ex) {
blackList.add(className); // This instance need not autowired.
}
}
}
ISyringe是apt在注解@Autowired时自动生成一个对应的ISyringe实现。将bundle中的数据取出,赋值给@Autowired注解的属性。
总的参数注入过程:
- ARouter.inject-->_ARouter.inject
- AutowiredServiceImpl.autowire
- 生成apt自动生成的ISyringe类的实例
- ISyringe。inject将Poster中的mBundle参数赋值给具体的属性
先通过开启AutowiredService来实现