ARouter源码分析-初始化
2020-07-16 本文已影响0人
dashingqi
Android_Banner.jpg
简介
- ARouter的初始化很简单,在Application的onCreate()中,一行代码就可以
ARouter.init(this)
- 看似简单的一行代码,其实背后也为我们做了不少工作,解下来就打开ARouter的源码大门,让我们一探究竟
初始化源码分析
ARouter # init()
ARouter.init(this)
// 此处调用了ARouter的init方法,让我们看下 init()方法
public static void init(Application application) {
//判断是否进行过初始化操作
if (!hasInit) {
logger = _ARouter.logger;
_ARouter.logger.info(Consts.TAG, "ARouter init start.");
// ----> 分析1
hasInit = _ARouter.init(application);
if (hasInit) {
_ARouter.afterInit();
}
_ARouter.logger.info(Consts.TAG, "ARouter init over.");
}
}
- 分析1:我们看到,如果ARouter没有进行过初始化操作,就调用了_ARouter.init()
_ARouter # init()
protected static synchronized boolean init(Application application) {
mContext = application;
// ----> 分析1
LogisticsCenter.init(mContext, executor);
//打印日志,ARouter初始化成功,看来上面的一行代码很重要啊
logger.info(Consts.TAG, "ARouter init success!");
// ARouter是否初始化的标志设置为true
hasInit = true;
mHandler = new Handler(Looper.getMainLooper());
return true;
}
- 分析1:此处调用了 LogisticsCenter.init(),字面意思LogisticsCenter就是物流中心,该类应该起到承上启下的作用把,我们看下它
LogisticsCenter # init()
//该方法接受两个参数 上下文和一个线程池
public synchronized static void init(Context context, ThreadPoolExecutor tpe) throws HandlerException {
mContext = context;
executor = tpe;
try {
long startInit = System.currentTimeMillis();
----> 分析1
loadRouterMap();
if (registerByPlugin) {
logger.info(TAG, "Load router map by arouter-auto-register plugin.");
} else {
Set<String> routerMap;
// 如果时debug模式,或者App升级版本了,那么routerMap中存储的值就需要重新获取了
if (ARouter.debuggable() || PackageUtils.isNewVersion(context)) {
logger.info(TAG, "Run with debug mode or new install, rebuild router map.");
// ROUTE_ROOT_PAKCAGE 对应着 com.alibaba.android.arouter.routes
// 在编译期间 ARouter会使用APT技术,使用注解处理器扫描module中的注解,在process方法中生成相应的代码文件
// 生成的代码文件就放在com.alibaba.android.arouter.routes该包下
// ClassUtils.getFileNameByPackageName() 该方面就是根据提供的包,拿到该包下的ClassName
routerMap = ClassUtils.getFileNameByPackageName(mContext, ROUTE_ROOT_PAKCAGE);
if (!routerMap.isEmpty()) {
// 使用Sp做一下缓存
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
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();
// 循环遍历拿到的ClassName
for (String className : routerMap) {
//如果className是 com.alibaba.android.arouter.routes包下 以 Arouter$$Root开头的话
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);
}
// 如果ClassName 是com.alibaba.android.arouter.routes包下 以 ARouter$$Interceptors开头的
else if (className.startsWith(ROUTE_ROOT_PAKCAGE + DOT + SDK_NAME + SEPARATOR + SUFFIX_INTERCEPTORS)) {
// Load interceptorMeta
((IInterceptorGroup) (Class.forName(className).getConstructor().newInstance())).loadInto(Warehouse.interceptorsIndex);
}
// 如果ClassName 是com.alibaba.android.arouter.routes包下 以ARouter$$Providers开头的
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() + "]");
}
}
总结
- ARouter的初始化就是拿到com.alibaba.android.arouter.routes包下类的ClassName,该包下的类都是在编译期间使用注解处理器生成的。有 Group、Root、Provider、Interceptor类型的。
- 拿到包下类的ClassName后,进行分类,通过反射拿到相应类的实例,调用loadInto方法,将数据存储到数据仓库(WarseHouse)中的集合中
- 这里面仅仅会初始化存储 一级路径与路由地址清单类的映射关系,一级 Provider和Interceptor类型的。至于每组对应的路由清单文件类,会在第一次页面跳转的时候,找到对应组下的路由清单进行初始化。