ARouter源码详解,零基础学习android编程

本文详细解析了ARouter的源码,包括如何通过ARouter实例构建路由并跳转到Activity,注解的使用,以及拦截器的工作原理。文章介绍了`Postcard`对象在跳转过程中的作用,`_ARouter`类中的导航方法,以及`InterceptorService`的初始化和拦截处理。特别强调了`Interceptor`注解的使用和拦截器的处理流程,展示了注解处理器在ARouter中的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

ARouter.getInstance().build(RoutePath.USER_HOME).navigation()

复制代码

《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》

【docs.qq.com/doc/DSkNLaERkbnFoS0ZF】 完整内容开源分享

build() 方法会通过 ARouter 中转调用到 _ARouterbuild() 方法,最终返回一个 Postcard 对象

/**

  • Build postcard by path and default group

*/

protected Postcard build(String path) {

if (TextUtils.isEmpty(path)) {

throw new HandlerException(Consts.TAG + “Parameter is invalid!”);

} else {

PathReplaceService pService = ARouter.getInstance().navigation(PathReplaceService.class);

if (null != pService) {

//用于路径替换,这对于某些需要控制页面跳转流程的场景比较有用

//例如,如果某个页面需要登录才可以展示的话

//就可以通过 PathReplaceService 将 path 替换 loginPagePath

path = pService.forString(path);

}

//使用字符串 path 包含的第一个单词作为 group

return build(path, extractGroup(path));

}

}

/**

  • Build postcard by path and group

*/

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);

}

}

复制代码

返回的 Postcard 对象可以用于传入一些跳转配置参数,例如:携带参数 mBundle、开启绿色通道 greenChannel 、跳转动画 optionsCompat

public final class Postcard extends RouteMeta {

// Base

private Uri uri;

private Object tag; // A tag prepare for some thing wrong.

private Bundle mBundle; // Data to transform

private int flags = -1; // Flags of route

private int timeout = 300; // Navigation timeout, TimeUnit.Second

private IProvider provider; // It will be set value, if this postcard was provider.

private boolean greenChannel;

private SerializationService serializationService;

}

复制代码

Postcardnavigation() 方法又会调用到 _ARouter 的以下方法来完成 Activity 的跳转。该方法逻辑上并不复杂,注释也写得很清楚了

final class _ARouter {

/**

  • Use router navigation.

  • @param context Activity or null.

  • @param postcard Route metas

  • @param requestCode RequestCode

  • @param callback cb

*/

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.

//用于执行跳转前的预处理操作,可以通过 onPretreatment 方法的返回值决定是否取消跳转

return null;

}

try {

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) {

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(context, 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 {

//开启了绿色通道,直接跳转,不需要遍历拦截器

return _navigation(context, postcard, requestCode, callback);

}

return null;

}

//由于本例子的目标页面是 Activity,所以只看 ACTIVITY 即可

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:

// Build intent

//Destination 就是指向目标 Activity 的 class 对象

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)) { // Non activity, need less one flag.

intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

}

// Set Actions

String action = postcard.getAction();

if (!TextUtils.isEmpty(action)) {

intent.setAction(action);

}

// Navigation in main looper.

//最终在主线程完成跳转

runInMainThread(new Runnable() {

@Override

public void run() {

startActivity(requestCode, currentContext, intent, postcard, callback);

}

});

break;

··· //省略其它类型判断

}

return null;

}

}

复制代码

navigation 方法的重点在于 LogisticsCenter.completion(postcard) 这一句代码。在讲 ARouter 初始化流程的时候有讲到:等到后续需要跳转到 groupaccount 的页面时,就会再来反射调用 ARouter$$Group$$accountloadInto 方法,即按需加载,等到需要的时候再来获取详细的路由对应信息

completion 方法就是用来获取详细的路由对应信息的。该方法会通过 postcard 携带的 path 和 group 信息从 Warehouse 取值,如果值不为 null 的话就将信息保存到 postcard 中,如果值为 null 的话就抛出 NoRouteFoundException

/**

  • Completion the postcard by route metas

  • @param postcard Incomplete postcard, should complete by this method.

*/

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) { //为 null 说明目标类不存在或者是该 group 还未加载过

Class<? extends IRouteGroup> groupMeta = Warehouse.groupsIndex.get(postcard.getGroup()); // Load route meta.

if (null == groupMeta) {

//groupMeta 为 null,说明 postcard 的 path 对应的 group 不存在,抛出异常

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值