我们找到Arouter的入口,也就是初始化的地方:
if (isDebug()) { // 这两行必须写在init之前,否则这些配置在init过程中将无效 ARouter.openLog(); // 打印日志 ARouter.openDebug(); // 开启调试模式(如果在InstantRun模式下运行,必须开启调试模式!线上版本需要关闭,否则有安全风险)}ARouter.init(mApplication); // 尽可能早,推荐在Application中初始化我们直接看ARouter.init方法
/** * Init, it must be call before used router.
*/
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.java 实现
protected static synchronized boolean init(Application application) { mContext = application; LogisticsCenter.init(mContext, executor); // 实际初始化的地方 logger.info(Consts.TAG, "ARouter init success!"); hasInit = true; return true; }我们只关注重点,LogisticsCenter.init(mContext, executor);,executor是一个线程池。
主要实现都在 LogisticsCenter.init 方法 中, 继续查看
public synchronized static void init(Context context, ThreadPoolExecutor tpe) throws HandlerException { mContext = context; executor = tpe; ... Set<String> routerMap;//生成类的类名集合 // 如果是debug模式或者是新版本,从apt生成的包中加载类 if (ARouter.debuggable() || PackageUtils.isNewVersion(context)) { // ClassUtils.getFileNameByPackageName 就是根据报名查找对应报名下的类, 就不贴代码了.. 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); //更新版本 } else {//否则从缓存读取类名 routerMap = new HashSet<>(context.getSharedPreferences(AROUTER_SP_CACHE_KEY, Context.MODE_PRIVATE).getStringSet(AROUTER_SP_KEY_MAP, new HashSet<String>())); } //判断类型,使用反射实例化对象,并调用方法 // 遍历获取到的 class for (String className : routerMap) { if (className.startsWith(ROUTE_ROOT_PAKCAGE + DOT + SDK_NAME + SEPARATOR + SUFFIX_ROOT)) { ((IRouteRoot) (Class.forName(className).getConstructor().newInstance())).loadInto(Warehouse.groupsIndex); } else if (className.startsWith(ROUTE_ROOT_PAKCAGE + DOT + SDK_NAME + SEPARATOR + SUFFIX_INTERCEPTORS)) { ((IInterceptorGroup) (Class.forName(className).getConstructor().newInstance())).loadInto(Warehouse.interceptorsIndex); } else if (className.startsWith(ROUTE_ROOT_PAKCAGE + DOT + SDK_NAME + SEPARATOR + SUFFIX_PROVIDERS)) { ((IProviderGroup) (Class.forName(className).getConstructor().newInstance())).loadInto(Warehouse.providersIndex); }`ROUTE_ROOT_PAKCAGE`是一个常量:```javapublic static final String ROUTE_ROOT_PAKCAGE = "com.alibaba.android.arouter.routes";而ClassUtils.getFileNameByPackageName方法做的就是找到app的dex,然后遍历出其中的属于com.alibaba.android.arouter.routes包下的所有类名,打包成集合返回。可以想象遍历整个dex查找指定类名的工作量有多大,怎么办呢?
就需要arouter-gradle-plugin ASM插桩 来解决这个非常耗费性能问题
可以看到初始化就是查找com.alibaba.android.arouter.routes包下的类, 获取实例并强制转化成IRouteRoot,
IInterceptorGroup, IProviderGroup, 然后调用 loadInto 方法.
通过 demo 的代码查找能看到有
com.alibaba.android.arouter.routes.ARouter$$Root$$app这样的类
// ARouter$$Root$$app.java/** * DO NOT EDIT THIS FILE!!! IT WAS GENERATED BY AROUTER. */
public class ARouter$$Root$$app implements IRouteRoot {
public void loadInto(Map<String, Class<? extends IRouteGroup>> routes) {
// 以分组做为 key, 缓存到 routes.
// routes 是指向 Warehouse.groupsIndex 的引用
routes.put("service", ARouter$$Group$$service.class);
routes.put("test", ARouter$$Group$$test.class);
}
}可以看到这是在编译期通过分析注解生成的代码.ARouter$$Group$$service.class也是生成.
// ARouter$$Group$$service.java/** * DO NOT EDIT THIS FILE!!! IT WAS GENERATED BY AROUTER. */
public class ARouter$$Group$$service implements IRouteGroup {
@Override
public void loadInto(Map<String, RouteMeta> atlas) {
atlas.put("/service/hello", RouteMeta.build(RouteType.PROVIDER, HelloServiceImpl.class, "/service/hello", "service", null, -1, -2147483648));
...
}
}到这里可以看到demo代码里定义的HelloServiceImpl.java 等出现了. 其实 ARouter
就是通过分析注解在编译期自动生成了一些关联代码. 另外的 Interceptors, Providers 逻辑上类似.
Interceptors 是注册了声明 Interceptor 注解, 并实现 IInterceptor 接口的类, Providers 是注册了声明
Route 注解, 并实现了 IProvider 接口的类
初始化工作都做完了, 总结一下 ARouter 会在编译期根据注解声明分析自动生成一些注入代码, 初始化工作主要是把这些注解的对象和对注解的配置缓存到
Warehouse 的静态对象中.
// 跳转activity的调用ARouter.getInstance().build("/test/activity2").navigation();// ARouter.java public Postcard build(String path) { return _ARouter.getInstance().build(path);}// _ARouter.java// group 默认是传进来的 path 第一部分内容. 例如 path = /test/activity1, group会默认为 test// 如果手动声明的,一定要手动传递, 不然会找不到protected Postcard build(String path, String group) { return new Postcard(path, group);}这里就是直接返回了一个 Postcard 对象, 并保存了path, group. Postcard 是继承了 RouteMeta
navigation方法最后都要调用的 _ARouter.java 中, 中间过程省略.我们直接看核心代码
// _ARouter.java// postcard 就是前面用build 方法构造的对象实例// requestCode 是区分 startAcitivity 的方式.如果不为-1, 就用startActivityForResult的方式启动// NavigationCallback 是对各种状态的回调. protected Object navigation(final Context context, final Postcard postcard, final int requestCode, final NavigationCallback callback) { try { // 验证是否能找到对应的 postcard.path LogisticsCenter.completion(postcard); } catch (NoRouteFoundException ex) { // 如果没找到postcard的配置, 调用onLost回调方法, 或者系统配置的"降级服务"(DegradeService)回调 if (null != callback) { callback.onLost(postcard); } else { DegradeService degradeService = ARouter.getInstance().navigation(DegradeService.class); if (null != degradeService) { degradeService.onLost(context, postcard); } } return null; } ... }navigation调用了LogisticsCenter.completion方法做验证, 我们看下 LogisticsCenter.java
这个方法如何验证 postcard, 然后再继续看navigation方法下面的逻辑
// LogisticsCenter.javapublic synchronized static void completion(Postcard postcard) { // 通过postcard 的 path 查找对应的 RouteMeta RouteMeta routeMeta = Warehouse.routes.get(postcard.getPath()); if (null == routeMeta) { // 如果没找到, 可能是还没装载过, 需要根据 group 查找对应的 groups Class<? extends IRouteGroup> groupMeta = Warehouse.groupsIndex.get(postcard.getGroup()); if (null == groupMeta) { // 如果没找到, 抛出 NoRouteFoundException 错误方法结束 throw new NoRouteFoundException(TAG + "There is no route match the path [" + postcard.getPath() + "], in group [" + postcard.getGroup() + "]"); } else { // 返回 IRouteGroup 对象, 并调用 loadInto方法. IRouteGroup iGroupInstance = groupMeta.getConstructor().newInstance(); iGroupInstance.loadInto(Warehouse.routes); // 删除 group 缓存 Warehouse.groupsIndex.remove(postcard.getGroup()); // 重新调用 completion 方法,此时对应的 group 已经缓存完成 completion(postcard); // Reload } } else { // 可以查找到 routeMeta, copy routeMeta 的原始数据到 postcard 中. postcard.setDestination(routeMeta.getDestination()); postcard.setType(routeMeta.getType()); postcard.setPriority(routeMeta.getPriority()); postcard.setExtra(routeMeta.getExtra()); switch (routeMeta.getType()) { case PROVIDER: Class<? extends IProvider> providerMeta = (Class<? extends IProvider>) routeMeta.getDestination(); IProvider instance = Warehouse.providers.get(providerMeta); // 初始化 provider 对象, 并调用初始化方法, 缓存到Warehouse.providers中. if (null == instance) { 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()); } } // 设置一个provider 引用 postcard.setProvider(instance); // provider 默认设置跳过拦截器 postcard.greenChannel(); break; case FRAGMENT: // fragment 默认设置跳过拦截器 postcard.greenChannel(); default: break; } }}completion方法主要是对 group 做一次懒式加载, 我们继续查看 navigation 方法下面的内容:
protected Object navigation(final Context context, final Postcard postcard, final int requestCode, final NavigationCallback callback) { ... // 执行到这里就是找到了 postcard. 执行对应回调 if (null != callback) { callback.onFound(postcard); } // 如果是"绿色通道", 则直接执行_navigation方法, 目前只有provider, fragment 默认是走绿色通道 if (!postcard.isGreenChannel()) { // interceptorService 是 ARouter 配置的默认的拦截服务 interceptorService.doInterceptions(postcard, new InterceptorCallback() { public void onContinue(Postcard postcard) { _navigation(context, postcard, requestCode, callback); } public void onInterrupt(Throwable exception) { if (null != callback) { callback.onInterrupt(postcard); } } }); } else { // 绿色通道 return _navigation(context, postcard, requestCode, callback); } return null; }interceptorService 是 ARouter
配置的默认的拦截器com.alibaba.android.arouter.core.InterceptorServiceImpl.java
public void doInterceptions(final Postcard postcard, final InterceptorCallback callback) { // 用线程池异步执行 LogisticsCenter.executor.execute(new Runnable() { public void run() { // 初始化一个同步计数类, 用拦截器的 size CancelableCountDownLatch interceptorCounter = new CancelableCountDownLatch(Warehouse.interceptors.size()); try { // 执行拦截操作, 看到这猜是递归调用.直到 index 满足条件, 退出递归. _excute(0, interceptorCounter, postcard); // 线程等待计数完成, 等待300秒... 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); } } });}我们继续看看_excute方法
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() { public void onContinue(Postcard postcard) { // 计数器减1 counter.countDown(); // 继续执行下一个拦截 _excute(index + 1, counter, postcard); } public void onInterrupt(Throwable exception) { // 当被拦截后退出递归 postcard.setTag(null == exception ? new HandlerException("No message.") : exception.getMessage()); counter.cancel(); } }); }}和我们猜测的一样, 一个标准的递归调用, 当所有拦截器执行后(假设都不做拦截), 最后还是要回到_navigation方法
private Object _navigation(final Context context, final Postcard postcard, final int requestCode, final NavigationCallback callback) { final Context currentContext = null == context ? mContext : context; // 我们就先只分析 activity 的逻辑 switch (postcard.getType()) { case ACTIVITY: // 初始化 intent, 把参数也添加上 final Intent intent = new Intent(currentContext, postcard.getDestination()); intent.putExtras(postcard.getExtras()); // Set flags. int flags = postcard.getFlags(); if (-1 != flags) { intent.setFlags(flags); } else if (!(currentContext instanceof Activity)) { intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); } // 在 UI 线程进行 start activity new Handler(Looper.getMainLooper()).post(new Runnable() { public void run() { if (requestCode > 0) { // Need start for result ActivityCompat.startActivityForResult((Activity) currentContext, intent, requestCode, postcard.getOptionsBundle()); } else { ActivityCompat.startActivity(currentContext, intent, postcard.getOptionsBundle()); } // 动画设置 if ((0 != postcard.getEnterAnim() || 0 != postcard.getExitAnim()) && currentContext instanceof Activity) { // Old version. ((Activity) currentContext).overridePendingTransition(postcard.getEnterAnim(), postcard.getExitAnim()); } if (null != callback) { // Navigation over. callback.onArrival(postcard); } } }); break; } return null;}``````java// 跳转activity的调用ARouter.getInstance().build("/test/activity2").navigation();// ARouter.java public Postcard build(String path) { return _ARouter.getInstance().build(path);}// _ARouter.java// group 默认是传进来的 path 第一部分内容. 例如 path = /test/activity1, group会默认为 test// 如果手动声明的,一定要手动传递, 不然会找不到protected Postcard build(String path, String group) { return new Postcard(path, group);}这里就是直接返回了一个 Postcard 对象, 并保存了path, group. Postcard 是继承了 RouteMeta
navigation方法最后都要调用的 _ARouter.java 中, 中间过程省略.我们直接看核心代码
// _ARouter.java// postcard 就是前面用build 方法构造的对象实例// requestCode 是区分 startAcitivity 的方式.如果不为-1, 就用startActivityForResult的方式启动// NavigationCallback 是对各种状态的回调. protected Object navigation(final Context context, final Postcard postcard, final int requestCode, final NavigationCallback callback) { try { // 验证是否能找到对应的 postcard.path LogisticsCenter.completion(postcard); } catch (NoRouteFoundException ex) { // 如果没找到postcard的配置, 调用onLost回调方法, 或者系统配置的"降级服务"(DegradeService)回调 if (null != callback) { callback.onLost(postcard); } else { DegradeService degradeService = ARouter.getInstance().navigation(DegradeService.class); if (null != degradeService) { degradeService.onLost(context, postcard); } } return null; } ... }navigation调用了LogisticsCenter.completion方法做验证, 我们看下 LogisticsCenter.java
这个方法如何验证 postcard, 然后再继续看navigation方法下面的逻辑
// LogisticsCenter.javapublic synchronized static void completion(Postcard postcard) { // 通过postcard 的 path 查找对应的 RouteMeta RouteMeta routeMeta = Warehouse.routes.get(postcard.getPath()); if (null == routeMeta) { // 如果没找到, 可能是还没装载过, 需要根据 group 查找对应的 groups Class<? extends IRouteGroup> groupMeta = Warehouse.groupsIndex.get(postcard.getGroup()); if (null == groupMeta) { // 如果没找到, 抛出 NoRouteFoundException 错误方法结束 throw new NoRouteFoundException(TAG + "There is no route match the path [" + postcard.getPath() + "], in group [" + postcard.getGroup() + "]"); } else { // 返回 IRouteGroup 对象, 并调用 loadInto方法. IRouteGroup iGroupInstance = groupMeta.getConstructor().newInstance(); iGroupInstance.loadInto(Warehouse.routes); // 删除 group 缓存 Warehouse.groupsIndex.remove(postcard.getGroup()); // 重新调用 completion 方法,此时对应的 group 已经缓存完成 completion(postcard); // Reload } } else { // 可以查找到 routeMeta, copy routeMeta 的原始数据到 postcard 中. postcard.setDestination(routeMeta.getDestination()); postcard.setType(routeMeta.getType()); postcard.setPriority(routeMeta.getPriority()); postcard.setExtra(routeMeta.getExtra()); switch (routeMeta.getType()) { case PROVIDER: Class<? extends IProvider> providerMeta = (Class<? extends IProvider>) routeMeta.getDestination(); IProvider instance = Warehouse.providers.get(providerMeta); // 初始化 provider 对象, 并调用初始化方法, 缓存到Warehouse.providers中. if (null == instance) { 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()); } } // 设置一个provider 引用 postcard.setProvider(instance); // provider 默认设置跳过拦截器 postcard.greenChannel(); break; case FRAGMENT: // fragment 默认设置跳过拦截器 postcard.greenChannel(); default: break; } }}completion方法主要是对 group 做一次懒式加载, 我们继续查看 navigation 方法下面的内容:
protected Object navigation(final Context context, final Postcard postcard, final int requestCode, final NavigationCallback callback) { ... // 执行到这里就是找到了 postcard. 执行对应回调 if (null != callback) { callback.onFound(postcard); } // 如果是"绿色通道", 则直接执行_navigation方法, 目前只有provider, fragment 默认是走绿色通道 if (!postcard.isGreenChannel()) { // interceptorService 是 ARouter 配置的默认的拦截服务 interceptorService.doInterceptions(postcard, new InterceptorCallback() { public void onContinue(Postcard postcard) { _navigation(context, postcard, requestCode, callback); } public void onInterrupt(Throwable exception) { if (null != callback) { callback.onInterrupt(postcard); } } }); } else { // 绿色通道 return _navigation(context, postcard, requestCode, callback); } return null; }interceptorService 是 ARouter
配置的默认的拦截器com.alibaba.android.arouter.core.InterceptorServiceImpl.java
public void doInterceptions(final Postcard postcard, final InterceptorCallback callback) { // 用线程池异步执行 LogisticsCenter.executor.execute(new Runnable() { public void run() { // 初始化一个同步计数类, 用拦截器的 size CancelableCountDownLatch interceptorCounter = new CancelableCountDownLatch(Warehouse.interceptors.size()); try { // 执行拦截操作, 看到这猜是递归调用.直到 index 满足条件, 退出递归. _excute(0, interceptorCounter, postcard); // 线程等待计数完成, 等待300秒... 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); } } });}我们继续看看_excute方法
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() { public void onContinue(Postcard postcard) { // 计数器减1 counter.countDown(); // 继续执行下一个拦截 _excute(index + 1, counter, postcard); } public void onInterrupt(Throwable exception) { // 当被拦截后退出递归 postcard.setTag(null == exception ? new HandlerException("No message.") : exception.getMessage()); counter.cancel(); } }); }}和我们猜测的一样, 一个标准的递归调用, 当所有拦截器执行后(假设都不做拦截), 最后还是要回到_navigation方法
private Object _navigation(final Context context, final Postcard postcard, final int requestCode, final NavigationCallback callback) { final Context currentContext = null == context ? mContext : context; // 我们就先只分析 activity 的逻辑 switch (postcard.getType()) { case ACTIVITY: // 初始化 intent, 把参数也添加上 final Intent intent = new Intent(currentContext, postcard.getDestination()); intent.putExtras(postcard.getExtras()); // Set flags. int flags = postcard.getFlags(); if (-1 != flags) { intent.setFlags(flags); } else if (!(currentContext instanceof Activity)) { intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); } // 在 UI 线程进行 start activity new Handler(Looper.getMainLooper()).post(new Runnable() { public void run() { if (requestCode > 0) { // Need start for result ActivityCompat.startActivityForResult((Activity) currentContext, intent, requestCode, postcard.getOptionsBundle()); } else { ActivityCompat.startActivity(currentContext, intent, postcard.getOptionsBundle()); } // 动画设置 if ((0 != postcard.getEnterAnim() || 0 != postcard.getExitAnim()) && currentContext instanceof Activity) { // Old version. ((Activity) currentContext).overridePendingTransition(postcard.getEnterAnim(), postcard.getExitAnim()); } if (null != callback) { // Navigation over. callback.onArrival(postcard); } } }); break; } return null;}主要实现是在LogisticsCenter.completion方法中对IProvider进行了一些分支处理
switch (routeMeta.getType()) { case PROVIDER: // 返回实现IProvider接口的类 Class<? extends IProvider> providerMeta = (Class<? extends IProvider>) routeMeta.getDestination(); // 在缓存中查找 IProvider instance = Warehouse.providers.get(providerMeta); // 初始化 provider 对象, 并调用初始化方法, 缓存到Warehouse.providers中. if (null == instance) { 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()); } } // 设置一个provider 引用 postcard.setProvider(instance); // provider 默认设置跳过拦截器 postcard.greenChannel(); break; // 可以看 _navigation 方法就是直接返回在 completion 方法中是设置的引用 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 PROVIDER: return postcard.getProvider(); } return null; }原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。