ARouter 源码解析:阿里推出的路由框架,教你一种更清晰的Android架构

本文深入解析了 ARouter 源码,包括 ClassName 的解析、Warehouse 的初始化、Postcard 的创建与补全以及执行跳转的整个流程。ARouter 是阿里巴巴推出的一款路由框架,通过源码分析,我们可以更好地理解和应用这个框架,实现更加清晰的 Android 应用架构。
摘要由CSDN通过智能技术生成

// …

} catch (Exception e) {

throw new HandlerException(TAG + “ARouter init logistics center exception! [” + e.getMessage() + “]”);

}

}

这里主要有如下几步:

  1. 获取 com.alibaba.android.arouter.routes 下存储 ClassName 的集合 routerMap

  2. 若为 debug 模式或之前没有解析过 routerMap,则通过 ClassUtils.getFileNameByPackageName 方法对指定 package 下的所有 ClassName 进行解析并存入 SP。

  3. 若并非 debug 模式,并且之前已经解析过,则直接从 SP 中取出。(debug 每次都需要更新,因为类会随着代码的修改而变动)

  4. 遍历 routerMap 中的 ClassName。

  5. 如果是 RouteRoot,则加载类构建对象后通过 loadInto 加载进 Warehouse.groupsIndex

  6. 如果是 InterceptorGroup,则加载类构建对象后通过 loadInto 加载进 Warehouse.interceptorsIndex

  7. 如果是 ProviderGroup,则加载类构建对象后通过 loadInto 加载进 Warehouse.providersIndex

解析 ClassName

我们先看看 ClassUtils.getFileNameByPackageName 是如何对指定 package 下的 ClassName 集合进行解析的:

public static Set getFileNameByPackageName(Context context, final String packageName) {

final Set classNames = new HashSet<>();

// 通过 getSourcePaths 方法获取 dex 文件 path 集合

List paths = getSourcePaths(context);

// 通过 CountDownLatch 对 path 的遍历处理进行控制

final CountDownLatch parserCtl = new CountDownLatch(paths.size());

// 遍历 path,通过 DefaultPoolExecutor 并发对 path 进行处理

for (final String path : paths) {

DefaultPoolExecutor.getInstance().execute(new Runnable() {

@Override

public void run() {

// 加载 path 对应的 dex 文件

DexFile dexfile = null;

try {

if (path.endsWith(EXTRACTED_SUFFIX)) {

// zip 结尾通过 DexFile.loadDex 进行加载

dexfile = DexFile.loadDex(path, path + “.tmp”, 0);

} else {

// 否则通过 new DexFile 加载

dexfile = new DexFile(path);

}

// 遍历 dex 中的 Entry

Enumeration dexEntries = dexfile.entries();

while (dexEntries.hasMoreElements()) {

// 如果是对应的 package 下的类,则添加其 className

String className = dexEntries.nextElement();

if (className.startsWith(packageName)) {

classNames.add(className);

}

}

} catch (Throwable ignore) {

Log.e(“ARouter”, “Scan map file in dex files made error.”, ignore);

} finally {

if (null != dexfile) {

try {

dexfile.close();

} catch (Throwable ignore) {

}

}

parserCtl.countDown();

}

}

});

}

// 所有 path 处理完成后,继续向下走

parserCtl.await();

Log.d(Consts.TAG, “Filter " + classNames.size() + " classes by packageName <” + packageName + “>”);

return classNames;

}

这里的步骤比较简单,主要是如下的步骤:

  1. 通过 getSourcePaths 方法获取 dex 文件的 path 集合。

  2. 创建了一个 CountDownLatch 控制 dex 文件的并行处理,以加快速度。

  3. 遍历 path 列表,通过 DefaultPoolExecutor 对 path 并行处理。

  4. 加载 path 对应的 dex 文件,并对其中的 Entry 进行遍历,若发现了对应 package 下的 ClassName,将其加入结果集合。

  5. 所有 dex 处理完成后,返回结果。

关于 getSourcePaths 如何获取到的 dex 集合这里就不纠结了,因为我们的关注点不在这里。

初始化 Warehouse

Warehouse 实际上就是仓库的意思,它存放了 ARouter 自动生成的类(RouteRootInterceptorGroupProviderGroup)的信息。

我们先看看 Warehouse 类究竟是怎样的:

class Warehouse {

// 保存 RouteGroup 对应的 class 以及 RouteMeta

static Map<String, Class<? extends IRouteGroup>> groupsIndex = new HashMap<>();

static Map<String, RouteMeta> routes = new HashMap<>();

// 保存 Provider 以及 RouteMeta

static Map<Class, IProvider> providers = new HashMap<>();

static Map<String, RouteMeta> providersIndex = new HashMap<>();

// 保存 Interceptor 对应的 class 以及 Inteceptor

static Map<Integer, Class<? extends IInterceptor>> interceptorsIndex = new UniqueKeyTreeMap<>(“More than one interceptors use same priority [%s]”);

static List interceptors = new ArrayList<>();

static void clear() {

routes.clear(

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值