文章目录
- 简介
- 介绍
- 作用
- 原理
- 关系
- 使用
- 添加依赖和配置
- 初始化SDK
- 添加注解在目标界面
- 跳转界面不带参
- 跳转界面含参
- 处理返回结果
- 源码
- 基本流程
- getInstance()
- build()
- navigation()
- _navigation()
- Warehouse
- ARouter初始化
- init
- 帮助类
- 根帮助类
- 组帮助类
- completion
- 总结
简介
介绍
ARouter 是阿里巴巴开源的一款 Android 路由框架,专为组件化架构设计,用于模块之间的页面跳转和服务通信。
ARouter 是路由系统,给无依赖的双方提供通信和路由的能力
作用
- 页面路由(页面跳转)
- 通过简单的路由配置,实现模块间页面跳转,避免直接依赖具体类,降低耦合度。
- 支持跨模块的页面跳转,即使页面所属模块在不同的
APK
中。
- 服务发现与调用
- 提供服务注册与发现机制,可以实现模块间的接口调用。
- 通过依赖注入机制简化服务调用流程,提升开发效率。
- 动态传参
- 支持页面跳转时传递参数(基本类型、对象等)。
- 支持通过注解方式接收参数,省去解析逻辑。
原理
关系
- 1.注册
B界面将类的信息,通过key-value的形式,注册到arouter中。
- 2.查询
A界面将类信息与额外信息(传输参数、跳转动画等),通过key传递至arouter中,并查询对应需要跳转类的信息。
- 3.结合
将A界面类信息、参数与B界面的类信息进行封装结合。
- 4.跳转
将结合后的信息,使用startActivity实现跳转。
使用
添加依赖和配置
android {defaultConfig {...javaCompileOptions {annotationProcessorOptions {arguments = [AROUTER_MODULE_NAME: project.getName()]}}}
}dependencies {implementation 'com.alibaba:arouter-api:x.x.x'annotationProcessor 'com.alibaba:arouter-compiler:x.x.x'...
}
在 gradle.properties
文件中添加如下行来启用 Jetifier:
主要用于自动将旧版的 Android 库(即基于 Support Library
的库)迁移为 AndroidX
兼容版本。
android.enableJetifier=true
初始化SDK
if (isDebug()) { // 这两行必须写在init之前,否则这些配置在init过程中将无效ARouter.openLog(); // 打印日志ARouter.openDebug(); // 开启调试模式(如果在InstantRun模式下运行,必须开启调试模式!线上版本需要关闭,否则有安全风险)
}
ARouter.init(mApplication); // 尽可能早,推荐在Application中初始化
我们可以在Application中初始化
public class MyApplication extends Application {@Overridepublic void onCreate() {super.onCreate();// 仅在调试模式下开启日志和调试模式if(BuildConfig.DEBUG){ARouter.openLog();ARouter.openDebug();}ARouter.init(this);}
}
添加注解在目标界面
// 在支持路由的页面上添加注解
// 路径注意至少需有两级,/xx/xx
@Route(path = "/test/second")
public class SecondActivity extends AppCompatActivity {
跳转界面不带参
public class MainActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);}public void startActivity(View view) {ARouter.getInstance().build("/test/SecondActivity").navigation();}
}
这里跳转放在onCreate里报错:可能是因为ARouter 未初始化完成,初始化放在onCrete里就好了
public class MainActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);// 仅在调试模式下开启日志和调试模式if(BuildConfig.DEBUG){ARouter.openLog();ARouter.openDebug();}ARouter.init(getApplication());ARouter.getInstance().build("/test/SecondActivity").navigation();} }
跳转界面含参
// 1
ARouter.getInstance().build("/test/SecondActivity").withString("key1", "123").withBoolean("key2", false).navigation();// 2
@Route(path = "/test/SecondActivity")
public class SecondActivity extends AppCompatActivity {public String key1;@Autowired(name = "key2")public boolean aBoolean;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_second);ARouter.getInstance().inject(this);Log.d("SecondActivityTag", key1 + " " + aBoolean);}
}
处理返回结果
如果需要在跳转到新页面并返回结果,可以使用 ARouter.getInstance().build()
方法构建路由请求时,调用 navigation()
方法的重载版本,传入一个 NavigationCallback
回调接口来处理返回结果
ARouter.getInstance().build("/main/selectActivity").navigation(this, new NavigationCallback() {@Overridepublic void onFound(Postcard postcard) {// 找到目标页面}@Overridepublic void onLost(Postcard postcard) {// 找不到目标页面}@Overridepublic void onArrival(Postcard postcard) {// 到达目标页面}@Overridepublic void onInterrupt(Postcard postcard) {// 路由被拦截}});
源码
基本流程
getInstance()
ARouter.getInstance().build("/test/SecondActivity").navigation();
双检锁,获取ARouter类的单例
public static ARouter getInstance() {if (!hasInit) {throw new InitException("ARouter::Init::Invoke init(context) first!");} else {if (instance == null) {synchronized (ARouter.class) {if (instance == null) {instance = new ARouter();}}}return instance;}
}
build()
这里使用了门面模式。外部调用者只需与 ARouter
交互,获取路由对象,不需要了解 _ARouter
内部如何管理单例、如何创建 Postcard
等。
build返回一个Postcard,
// ARouter.java
public Postcard build(String path) {return _ARouter.getInstance().build(path);
}
// _ARouter.java
protected Postcard build(String path) {if (TextUtils.isEmpty(path)) {throw new HandlerException(Consts.TAG + "Parameter is invalid!");} else {// 预处理替换: 有需求来对 path 做统一的预处理就实现 PathReplaceService PathReplaceService pService = ARouter.getInstance().navigation(PathReplaceService.class);if (null != pService) {path = pService.forString(path);}// extractGroup()方法提取path的组名return build(path, extractGroup(path), true);}
}
这里返回new出的一个Postcard对象,包含他的path和组名
protected Postcard build(String path, String group, Boolean afterReplace) {if (TextUtils.isEmpty(path) || TextUtils.isEmpty(group)) {throw new HandlerException(Consts.TAG + "Parameter is invalid!");} else {if (!afterReplace) {PathReplaceService pService = ARouter.getInstance().navigation(PathReplaceService.class);if (null != pService) {path = pService.forString(path);}}return new Postcard(path, group);}
}
- Postcard 类
Postcard
类继承自 RouteMeta
,是路由的实际载体,包含导航需要的额外信息。它不仅继承了 RouteMeta
的基本字段,还添加了与导航操作密切相关的属性。
public final class Postcard extends RouteMeta {private Uri uri;private Object tag;private Bundle mBundle;private int flags = 0; private int timeout = 300; private IProvider provider; private boolean greenChannel; private SerializationService serializationService;private Context context; private String action;
}
上文创建Postcard对象时会通过set方法设置到父类RouteMeta的属性中
- RouteMeta 类
RouteMeta
是一个数据模型类,用于描述路由的元信息。该类中的属性用于存储路由目标、路径、分组及相关的附加信息。
public class RouteMeta {private RouteType type; // 路由类型 (枚举类型,标识不同的路由类型, 例如 ACTIVITY、SERVICE 等)private Element rawType; // 原始类型 (可能是路由的注解元素,用于生成代码时保留元信息)private Class<?> destination; // 路由目标 (路由的目标类,例如某个 Activity 或 Fragment)private String path; // 路由路径 (唯一标识路由的字符串,例如 "/app/home")private String group; // 路由分组 (用于管理路由分组,例如 "app"、"user")private int priority = -1; // 路由优先级 (数值越小,优先级越高)private int extra; // 额外信息 (存储扩展数据,通常用于业务需求)private Map<String, Integer> paramsType; // 参数类型映射 (参数名与参数类型的映射,例如 {"id": String.class})private String name; // 路由名称 (可选字段,用于描述路由)
}
navigation()
导航
由上至下调用,然后调用到ARouter的navigation方法
该方法完成了从调用导航到实际路由跳转的逻辑处理
//_ARouter.java
protected Object navigation(final Context context, final Postcard postcard, final int requestCode, final NavigationCallback callback) {// 1.确保 Postcard 能绑定一个有效的 Contextpostcard.setContext(null == context ? mContext : context);try {// 2.根据路由路径完善 Postcard 的信息LogisticsCenter.completion(postcard);} catch (NoRouteFoundException ex) {logger.warning(Consts.TAG, ex.getMessage());// 调试功能if (debuggable()) {runInMainThread(new Runnable() {@Overridepublic void run() {Toast.makeText(mContext, "There's no route matched!\n" +" Path = [" + postcard.getPath() + "]\n" +" Group = [" + postcard.getGroup() + "]", Toast.LENGTH_LONG).show();}});}// 2.1 捕获到异常:Postcard 路径不存在// 存在回调接口,就通知调用 onLost() 方法。if (null != callback) {callback.onLost(postcard);} else {// 不存在回调接口,执行全局降级服务,调用onLost方法,当路由丢失时可以做一些事情。DegradeService degradeService = ARouter.getInstance().navigation(DegradeService.class);if (null != degradeService) {degradeService.onLost(context, postcard);}}return null;}// 2.2 没捕获到异常,回调onFound方法if (null != callback) {callback.onFound(postcard);}// 3.1 不是绿色通道,拦截器进行处理// 拦截器:扩展,允许开发者在导航过程中插入自定义逻辑,比如权限检查、登录验证或其他操作。// onContinue():继续路由操作。// onInterrupt():终止路由操作,并通知回调接口 onInterrupt()。if (!postcard.isGreenChannel()) { interceptorService.doInterceptions(postcard, new InterceptorCallback() {@Overridepublic void onContinue(Postcard postcard) {_navigation(postcard, requestCode, callback);}@Overridepublic void onInterrupt(Throwable exception) {if (null != callback) {callback.onInterrupt(postcard);}logger.info(Consts.TAG, "Navigation failed, termination by interceptor : " + exception.getMessage());}});} else {// 如果 isGreenChannel() 返回 true,则跳过拦截器,直接导航。// 开发模式下跳过非必要检查,加速导航return _navigation(postcard, requestCode, callback);}return null;
}
总结:该方法完善了postcard的信息,路径验证,拦截器逻辑
最后调用的_navigation将执行跳转逻辑
_navigation()
private Object _navigation(final Postcard postcard, final int requestCode, final NavigationCallback callback) {final Context currentContext = postcard.getContext();// 根据路由类型switch (postcard.getType()) {// 1.跳转到活动case ACTIVITY:// 通过getDestination()方法拿到目标页面的 Classfinal Intent intent = new Intent(currentContext, postcard.getDestination());intent.putExtras(postcard.getExtras());// 设置标志位(可选)int flags = postcard.getFlags();if (0 != flags) {intent.setFlags(flags);}// 如果当前上下文不是一个 Activity,则添加 FLAG_ACTIVITY_NEW_TASK,确保能够从非 Activity 环境启动目标页面。if (!(currentContext instanceof Activity)) {intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);}// 设置 ActionsString action = postcard.getAction();if (!TextUtils.isEmpty(action)) {intent.setAction(action);}// 在主线程启动 ActivityrunInMainThread(new Runnable() {@Overridepublic void run() {startActivity(requestCode, currentContext, intent, postcard, callback);}});break;// 想要获取的服务,即IProvider的实现类。case PROVIDER:return postcard.getProvider();// 下面三个都是通过反射创建实例case BOARDCAST:case CONTENT_PROVIDER:case FRAGMENT:// 通过getDestination得到目标类对象Class<?> fragmentMeta = postcard.getDestination();try {// 通过反射构造Object instance = fragmentMeta.getConstructor().newInstance();// 类型判断,适配不同类型的fragmentif (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());}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;
}
Warehouse
我们在navigation方法中调用了LogisticsCenter.completion(postcard);
,来完善了postcard的信息
completion
里出现了Warehouse,我们看看是什么
Warehouse
用于存储路由表和相关的映射数据结构。它是 ARouter 的“仓库”,负责管理路由信息的加载、存储和查询。
主要职责是作为数据中心,保存路由信息、拦截器、服务等的映射关系。它将这些信息加载到内存中,方便 ARouter 在运行时快速查找目标页面或功能。
// Warehouse.java
class Warehouse {static Map<String, Class<? extends IRouteGroup>> groupsIndex = new HashMap<>(); static Map<String, RouteMeta> routes = new HashMap<>();static Map<Class, IProvider> providers = new HashMap<>();static Map<String, RouteMeta> providersIndex = new HashMap<>();static Map<Integer, Class<? extends IInterceptor>> interceptorsIndex = new UniqueKeyTreeMap<>("...");static List<IInterceptor> interceptors = new ArrayList<>();static void clear() {routes.clear();groupsIndex.clear();providers.clear();providersIndex.clear();interceptors.clear();interceptorsIndex.clear();}
}
在 ARouter 中,路由表、拦截器表、服务表分别用来管理路由路径、拦截器以及服务的相关信息,从而实现模块化开发、路径导航、拦截器链、以及服务的统一管理。以下是关于各部分的详细分析:
- 路由表
groupsIndex
-
存储路由组名到具体路由组类的映射。通过这种分组方式,可以有效减少路由加载的时间和内存占用。
-
public static Map<String, Class<? extends IRouteGroup>> groupsIndex = new HashMap<>();
- Key:路由组名(如
"user"
),表示属于哪个功能模块。 - Value:实现了
IRouteGroup
接口的类,用于提供具体的路由信息。
- Key:路由组名(如
-
当访问一个路由路径时,ARouter 首先查找该路径所属的组(
groupsIndex
中的 Key)。通过路由组类(Value)加载组内所有路由信息到
routes
。
routes
-
存储完整路由路径到**路由元信息(
RouteMeta
)**的映射。 -
public static Map<String, RouteMeta> routes = new HashMap<>();
- Key:完整路径(如
/user/profile
)。 - Value:
RouteMeta
对象,包含目标页面类、参数、类型等信息。
- Key:完整路径(如
-
在
groupsIndex
确定路由组后,通过组加载具体的路由信息到routes
中。最终通过路径快速定位到
RouteMeta
。
- 拦截器表
interceptorsIndex
-
管理拦截器的优先级和对应的实现类,方便构建拦截器链。
-
public static Map<Integer, Class<? extends IInterceptor>> interceptorsIndex = new HashMap<>();
- Key:拦截器优先级(
Priority
),数字越小优先级越高。 - Value:拦截器类(
IInterceptor
的实现类)。
- Key:拦截器优先级(
-
允许开发者在路由跳转前拦截请求、检查参数、处理权限等。
interceptors
-
缓存所有拦截器的实例。
-
static List<IInterceptor> interceptors = new ArrayList<>();
-
路由跳转时,从
interceptors
依次执行所有拦截器。 -
开发者可以实现拦截器逻辑,比如登录验证、动态权限申请等。
- 服务表
providers
-
缓存服务实例(
IProvider
),用于提供功能模块的具体实现。 -
static Map<Class, IProvider> providers = new HashMap<>();
- Key:服务接口的
Class
对象。 - Value:服务接口的具体实现实例。
- Key:服务接口的
-
在应用中实现全局服务调用。
例如:网络管理器、日志管理器、用户管理等。
providersIndex
-
存储服务实现类的元信息,用于动态加载服务。
-
public static Map<String, RouteMeta> providersIndex = new HashMap<>();
- Key:服务类的全类名。
- Value:
RouteMeta
对象,包含服务实现类的信息。
-
路由初始化时,将服务实现类的信息加载到
providersIndex
。在需要服务时,通过
providersIndex
获取元信息并实例化服务。
Warehouse
的数据是在LogisticsCenter
类的init()
方法中被加载的
ARouter初始化
init
从ARouter.init()
出发
// ARouter.java
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;mHandler = new Handler(Looper.getMainLooper());return true;
}
// LogisticsCenter.java
public synchronized static void init(Context context, ThreadPoolExecutor tpe) throws HandlerException {// 保存上下文和线程池引用。mContext = context; executor = tpe;try {long startInit = System.currentTimeMillis(); // 尝试使用AGP加载路由表loadRouterMap(); if (registerByPlugin) {logger.info(TAG, "Load router map by arouter-auto-register plugin.");} else {Set<String> routerMap; // 路由表集合// 1. 如果是调试模式或是新安装应用,则重建路由表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"routerMap = ClassUtils.getFileNameByPackageName(mContext, ROUTE_ROOT_PAKCAGE);// 将路由表存储到 SharedPreferences 进行缓存,后续快速加载if (!routerMap.isEmpty()) {context.getSharedPreferences(AROUTER_SP_CACHE_KEY, Context.MODE_PRIVATE).edit().putStringSet(AROUTER_SP_KEY_MAP, routerMap).apply();}// 更新版本信息,避免重复更新PackageUtils.updateVersion(context);} else {// 2. 从缓存中加载路由表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>()));}//遍历帮助类,区分是哪种帮助类,然后反射创建帮助类实例后,调用其loadInto方法来填充Warehouse相应的Mapfor (String className : routerMap) {if (className.startsWith(ROUTE_ROOT_PAKCAGE + DOT + SDK_NAME + SEPARATOR + SUFFIX_ROOT)) {//类名开头:com.alibaba.android.arouter.routes.ARouter$$Root//填充Warehouse.groupsIndex,即所有IRouteGroup实现类的class对象((IRouteRoot) (Class.forName(className).getConstructor().newInstance())).loadInto(Warehouse.groupsIndex);} else if (className.startsWith(ROUTE_ROOT_PAKCAGE + DOT + SDK_NAME + SEPARATOR + SUFFIX_INTERCEPTORS)) {//类名开头:com.alibaba.android.arouter.routes.ARouter$$Interceptors//填充Warehouse.interceptorsIndex,即所有IInterceptor实现类的class对象((IInterceptorGroup) (Class.forName(className).getConstructor().newInstance())).loadInto(Warehouse.interceptorsIndex);} else if (className.startsWith(ROUTE_ROOT_PAKCAGE + DOT + SDK_NAME + SEPARATOR + SUFFIX_PROVIDERS)) {//类名开头:com.alibaba.android.arouter.routes.ARouter$$Providers//填充Warehouse.providersIndex,即所有provider的RouteMeta((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) {// 捕获异常并抛出 HandlerExceptionthrow new HandlerException(TAG + "ARouter init logistics center exception! [" + e.getMessage() + "]");}
}
总结:
- 确定路由表的加载方式(插件自动注册(编译时)或手动扫描(运行时)。
- 判断是否需要重建路由表(调试模式或版本变化)。
- 加载路由表信息到内存(通过反射机制调用生成的类)。
- 提供异常处理和性能数据统计。
帮助类
根帮助类
路由组元信息的收集是通过根帮助类
用来实现对 WareHouse.groupsIndex 赋值
static Map<String, Class<? extends IRouteGroup>> groupsIndex = new HashMap<>();
- 把path第一级相同的所以路由分到同一个组中。
key:组名
value:组帮助类
这里loadInto方法的参数类型就是groupsIndex的类型
// LogisticsCenter.java
public synchronized static void init(Context context, ThreadPoolExecutor tpe) throws HandlerException {...for (String className : routerMap) {if (className.startsWith(ROUTE_ROOT_PAKCAGE + DOT + SDK_NAME + SEPARATOR + SUFFIX_ROOT)) {//类名开头:com.alibaba.android.arouter.routes.ARouter$$Root//填充Warehouse.groupsIndex,即所有IRouteGroup实现类的class对象((IRouteRoot) (Class.forName(className).getConstructor().newInstance())).loadInto(Warehouse.groupsIndex);}...}
}
组帮助类
帮助WareHouse填充Warehouse.routes
static Map<String, RouteMeta> routes = new HashMap<>();
package com.alibaba.android.arouter.routes;
public class ARouter$$Group$$test implements IRouteGroup {@Overridepublic void loadInto(Map<String, RouteMeta> atlas) {atlas.put("/test/SecondActivity", RouteMeta.build(RouteType.ACTIVITY, SecondActivity.class, "/test/secondactivity", "test", new java.util.HashMap<String, Integer>(){{put("key1", 8); put("key2", 0); }}, -1, -2147483648));}
}
可以看到每个路由的目标类class被放在了RouteMeta
里
completion
/*** 尝试完成 Postcard 的路由信息填充,包括加载动态分组路由和设置目标类。** @param postcard 路由信息的载体,目前只包含 path 和 group 属性*/
public synchronized static void completion(Postcard postcard) {// 检查 Postcard 是否为空if (null == postcard) {throw new NoRouteFoundException(TAG + "No postcard!");}// 尝试通过 path 获取路由元信息RouteMeta routeMeta = Warehouse.routes.get(postcard.getPath());if (null == routeMeta) {// 如果未获取到路由元信息,检查是否有该组的帮助类if (!Warehouse.groupsIndex.containsKey(postcard.getGroup())) {throw new NoRouteFoundException(TAG + "There is no route match the path [" + postcard.getPath() + "], in group [" + postcard.getGroup() + "]");} else {try {// 如果存在该组的帮助类,加载该组的所有路由if (ARouter.debuggable()) {logger.debug(TAG, String.format(Locale.getDefault(), "The group [%s] starts loading, trigger by [%s]", postcard.getGroup(), postcard.getPath()));}// 加载分组路由addRouteGroupDynamic(postcard.getGroup(), null);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 以重新获取路由元信息completion(postcard);return;}} else {// 如果获取到路由元信息,将其同步到 Postcard 中postcard.setDestination(routeMeta.getDestination());postcard.setType(routeMeta.getType());postcard.setPriority(routeMeta.getPriority());postcard.setExtra(routeMeta.getExtra());// 如果包含原始 URI,则解析参数并设置到 Postcard 中Uri rawUri = postcard.getUri();if (null != rawUri) {Map<String, String> resultMap = TextUtils.splitQueryParameters(rawUri);Map<String, Integer> paramsType = routeMeta.getParamsType();if (MapUtils.isNotEmpty(paramsType)) {// 按类型设置参数值,仅处理使用 @Param 注解的参数for (Map.Entry<String, Integer> params : paramsType.entrySet()) {setValue(postcard, params.getValue(), params.getKey(), resultMap.get(params.getKey()));}// 保存需要自动注入的参数名postcard.getExtras().putStringArray(ARouter.AUTO_INJECT, paramsType.keySet().toArray(new String[]{}));}// 保存原始 URIpostcard.withString(ARouter.RAW_URI, rawUri.toString());}// 根据路由类型进一步处理switch (routeMeta.getType()) {case PROVIDER: // 如果是服务类型的路由// 确认目标类实现了 IProvider 接口Class<? extends IProvider> providerMeta = (Class<? extends IProvider>) routeMeta.getDestination();IProvider instance = Warehouse.providers.get(providerMeta);if (null == instance) { // 如果服务实例尚未创建try {// 创建服务实例并初始化IProvider provider = providerMeta.getConstructor().newInstance();provider.init(mContext);// 存入服务仓库Warehouse.providers.put(providerMeta, provider);instance = provider;} catch (Exception e) {logger.error(TAG, "Init provider failed!", e);throw new HandlerException("Init provider failed!");}}postcard.setProvider(instance); // 设置服务实例postcard.greenChannel(); // 跳过拦截器break;case FRAGMENT: // 如果是 Fragment 类型的路由postcard.greenChannel(); // Fragment 也跳过拦截器default:break;}}
}
尝试获取路由元信息 → 检查并加载路由组 → 同步元信息 → 判断目标类并处理
总结
参考:
- “终于懂了” 系列:组件化框架 ARouter 完全解析(一) 原理详解-腾讯云开发者社区-腾讯云 (tencent.com)
- ARouter源码解析(一)-腾讯云开发者社区-腾讯云 (tencent.com)
- ARouter/README_CN.md at master · alibaba/ARouter (github.com)