Arouter 源码解析
我们从常用的功能点入手,基本可了解到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主要执行了 _ARouter.init(application) 和_ARouter.afterInit() , 有些门面模式的设计意味
_ARouter.init(application)
java
static ILogger logger = new DefaultLogger(Consts.TAG);
.....
.....
//线程执行器,核心线程和最大线程相等,为设备cpu数+1
private volatile static ThreadPoolExecutor executor = DefaultPoolExecutor.getInstance();
private static Handler mHandler;
private static Context mContext;
private static InterceptorService interceptorService;
private _ARouter() {
}
protected static synchronized boolean init(Application application) {
mContext = application; // mContext为application context
//核心逻辑中心初始化,重点
LogisticsCenter.init(mContext, executor);
logger.info(Consts.TAG, "ARouter init success!");
hasInit = true;
mHandler = new Handler(Looper.getMainLooper()); // main线程handler
return true;
}
......
......
重点是 LogisticsCenter.init(mContext, executor);
java
public synchronized static void init(Context context, ThreadPoolExecutor tpe) throws HandlerException{
// 记录一下线程池和context
mContext = context;
executor = tpe;
......
......
Set<String> routerMap;
//如果版本发生更新或者是调试阶段
if(ARouter.debuggable()||PackageUtils.isNewVersion(context)){
//将com.alibaba.android.arouter.routes这个包下面的class加载到内存中,这个包下面的代码就是apt生成的代码
routerMap = ClassUtils.getFileNameByPackageName(mContext, ROUTE_ROOT_PAKCAGE);
......
......
}else{
......
}
// 将apt生成的class分类别处理,这里有3种类型:1.IRouteRoot 2.IInterceptorGroup 3.IProviderGroup
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);
}
}
}
将apt生成的代码分成3种类型:1.IRouteRoot ``2.IInterceptorGroup
3.IProviderGroup
IRouteRoot示例:
java
public class ARouter$$Root$$main implements IRouteRoot {
@Override
public void loadInto(Map<String, Class<? extends IRouteGroup>> routes) {
routes.put("module_main", ARouter$$Group$$module_main.class);
}
}
IRouteRoot加载了一个group对象ARouter$$Group$$module_main.class
ARouter$$Group$$module_main.class
java
public class ARouter$$Group$$module_main implements IRouteGroup {
@Override
public void loadInto(Map<String, RouteMeta> atlas) {
atlas.put("/module_main/application", RouteMeta.build(RouteType.PROVIDER, MainApplicationProvider.class, "/module_main/application", "module_main", null, -1, -2147483648));
}
}
ARouter$$Group$$module_main
加载了真实的RouteMeta
Arouter 通过反射调用IRouteRoot对象的loadInto方法,将IRouteGroup class加载到内存中,而IRouteGroup里面又包含了RouteMeta(我们常用的@Route 注解最终生成的信息)信息 ,**之所以不直接把RouteMeta
加载到内存,是一种懒加载的思路 **
同样的方式看IInterceptorGroup
和 IProviderGroup
最终解析的信息结果保存在Warehouse.java
java
class Warehouse {
// Cache route and metas,路由和RouteMeta,现阶段IRouteGroup信息保存groupsIndex中
static Map<String, Class<? extends IRouteGroup>> groupsIndex = new HashMap<>();
static Map<String, RouteMeta> routes = new HashMap<>();
// Cache provider
static Map<Class, IProvider> providers = new HashMap<>();
//现阶段,IProviderGroup信息保存在providersIndex中,providers map中没有内容
static Map<String, RouteMeta> providersIndex = new HashMap<>();
// Cache interceptor,同理,保存IInterceptorGroup信息
static Map<Integer, Class<? extends IInterceptor>> interceptorsIndex = new UniqueKeyTreeMap<>("More than one interceptors use same priority [%s]");
static List<IInterceptor> interceptors = new ArrayList<>();
static void clear() {
routes.clear();
groupsIndex.clear();
providers.clear();
providersIndex.clear();
interceptors.clear();
interceptorsIndex.clear();
}
}
_ARouter.afterInit()
java
//初始化拦截器,负值interceptorService
static void afterInit() {
// Trigger interceptor init, use byName.
interceptorService = (InterceptorService)ARouter.getInstance().build("/arouter/service/interceptor").navigation();
}
好了,初始化完成了apt生成的class的处理,将route信息,privider信息,interceptor信息加载到了内存中,放到Warehouse的属性里面
路由的使用
kotlin
ARouter.getInstance().build("/test/activity").withString("name", "ray").navigation();
这个步骤分为几个点:
1.ARouter调用Build生成Postcard,过程是怎样的
2.Postcard是什么
3.Postcard调用navigation是怎样执行的
生成Postcard
java
protected Postcard build(String path) {
if (TextUtils.isEmpty(path)) {
throw new HandlerException(Consts.TAG + "Parameter is invalid!");
} else {
//ARouter.getInstance().navigation是查找provider,pService = null
PathReplaceService pService = ARouter.getInstance().navigation(PathReplaceService.class);
if (null != pService) {
path = pService.forString(path);
}
return build(path, extractGroup(path), true);
}
}
/**
* Build postcard by path and group
*/
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);
}
}
// 生成Postcard, 传入path和group , group是路径中的第一个/间的内容
return new Postcard(path, group);
}
}
build生成了Postcard对象
Postcard是什么
首先Postcard继承RouteMeta,RouteMeta中存储的是关于route的一些基础信息,只定位于存储route基础信息。
java
public class RouteMeta {
private RouteType type; // Type of route
private Element rawType; // Raw type of route
private Class<?> destination; // Destination
private String path; // Path of route
private String group; // Group of route
private int priority = -1; // The smaller the number, the higher the priority
private int extra; // Extra data
private Map<String, Integer> paramsType; // Param type
private String name;
private Map<String, Autowired> injectConfig; // Cache inject config.
...
}
Postcard.java
java
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;
// Animation
private Bundle optionsCompat; // The transition animation of activity
private int enterAnim = -1;
private int exitAnim = -1;
...
public void navigation(Activity mContext, int requestCode, NavigationCallback callback){
ARouter.getInstance().navigation(mContext, this, requestCode, callback);
}
...
public Postcard withString(@Nullable String key, @Nullable String value) {
mBundle.putString(key, value);
return this;
}
...
public Postcard withTransition(int enterAnim, int exitAnim) {
this.enterAnim = enterAnim;
this.exitAnim = exitAnim;
return this;
}
...
}
虽然Postcard中有很多属性,但是此时,build生成的postcard对象中只有path
和`group,下面看看Postcard信息是如何被补齐的
Postcard调用navigation是怎样执行的
最终执行_Arouter的navigation
java
protected Object navigation(final Context context, final Postcard postcard, final int requestCode, final NavigationCallback callback) {
.....
try{
//补齐Postcard的信息
LogisticsCenter.completion(postcard);
} catch(Exception e){
......
}
......
......
//执行拦截器相关逻辑
interceptorService.doInterceptions(postcard, new InterceptorCallback(){
@Override
public void onContinue(Postcard postcard) {
_navigation(context, postcard, requestCode, callback);
}
@Override
public void onInterrupt(Throwable exception) {
if (null != callback) {
callback.onInterrupt(postcard);
}
}
}
//执行路由相关逻辑
return _navigation(context, postcard, requestCode, callback);
}
Postcard信息的补齐
java
//LogisticsCenter.java
public synchronized static void completion(Postcard postcard){
......
......
// 从Warehouse.routes中获取RouteMeta
RouteMeta routeMeta = Warehouse.routes.get(postcard.getPath());
if (null == routeMeta){
//第一次肯定获取RouteMeta不到,因为信息保存在Warehouse的groupsIndex中了,所以,接着从groupsIndex中取
Class<? extends IRouteGroup> groupMeta = Warehouse.groupsIndex.get(postcard.getGroup());
......
......
// 取出IRouteGroup
IRouteGroup iGroupInstance = groupMeta.getConstructor().newInstance();
// iGroupInstance内部的信息加载到Warehouse.routes中(用的时候meta加载到内存,懒加载啊)
iGroupInstance.loadInto(Warehouse.routes);
Warehouse.groupsIndex.remove(postcard.getGroup());
}
......
......
// postcard在这里初始化,知道了route目标的Destination,Type和其他信息,这里的type是区分目标是activity或者provider等
postcard.setDestination(routeMeta.getDestination());
postcard.setType(routeMeta.getType());
postcard.setPriority(routeMeta.getPriority());
postcard.setExtra(routeMeta.getExtra());
......
......
switch (routeMeta.getType()){
// 对于provider类型,先生成provider对象,然后初始化,保存到缓存中,防止多次重复创建,
case PROVIDER:
Class<? extends IProvider> providerMeta = (Class<? extends IProvider>) routeMeta.getDestination();
IProvider instance = Warehouse.providers.get(providerMeta);
if (null == instance) { // There's no instance of this provider
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());
}
}
postcard.setProvider(instance);
postcard.greenChannel(); // Provider should skip all of interceptors
break;
case FRAGMENT:
postcard.greenChannel();
default:
break;//
}
}
好了,此时我们跳转需要的信息就得到了补齐
执行路由相关逻辑
java
//_Arouter.java
private Object _navigation(final Context context, final Postcard postcard, final int requestCode, final NavigationCallback callback){
// 初始化当前context,mContext是application的负值
final Context currentContext = null == context ? mContext : context;
switch (postcard.getType()){
//如果是activity,执行跳转
case ACTIVITY:
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)) { // 如果是application context执行调整,flag需 要添加Intent.FLAG_ACTIVITY_NEW_TASK
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;
//如果是provider类型,返回provider对象实例
case PROVIDER:
return postcard.getProvider();
case BOARDCAST:
case CONTENT_PROVIDER:
// 如果是Fargment,通过反射创建Fargment对象实例,这种每次会创建新实例
case FRAGMENT:
Class fragmentMeta = postcard.getDestination();
try {
Object instance = fragmentMeta.getConstructor().newInstance();
if (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) {
......
......
}
}
}
拦截器相关逻辑
拦截器初始化:_ARouter.afterInit()
java
static void afterInit() {
// Trigger interceptor init, use byName.
interceptorService = (InterceptorService) ARouter.getInstance().build("/arouter/service/interceptor").navigation();
}
/arouter/service/interceptor
关联的类在com.alibaba.android.arouter.core.InterceptorServiceImpl
, InterceptorService
继承 IProvider
,所以,创建 InterceptorServiceImpl
实例时会调用init(context)
方法完成初始化
参考上面Postcard信息的补齐步骤
java
@Route(path = "/arouter/service/interceptor")
public class InterceptorServiceImpl implements InterceptorService{
private static boolean interceptorHasInit;
private static final Object interceptorInitLock = new Object();
......
......
@Override
public void init(final Context context) {
LogisticsCenter.executor.execute(new Runnable() {
@Override
public void run() {
if (MapUtils.isNotEmpty(Warehouse.interceptorsIndex)) {
//循环遍历Warehouse.interceptorsIndex
for (Map.Entry<Integer, Class<? extends IInterceptor>> entry : Warehouse.interceptorsIndex.entrySet()) {
Class<? extends IInterceptor> interceptorClass = entry.getValue();
try {
// 反射创建IInterceptor对象实例
IInterceptor iInterceptor = interceptorClass.getConstructor().newInstance();
//执行拦截器初始化
iInterceptor.init(context);
Warehouse.interceptors.add(iInterceptor);
} catch (Exception ex) {
throw new HandlerException(TAG + "ARouter init interceptor error! name = [" + interceptorClass.getName() + "], reason = [" + ex.getMessage() + "]");
}
}
interceptorHasInit = true;
logger.info(TAG, "ARouter interceptors init over.");
synchronized (interceptorInitLock) {
interceptorInitLock.notifyAll();
}
}
}
});
}
}
而Warehouse.interceptorsIndex
中的拦截器的class
对象是在初始化的时候加载到内存中的
java
//LogisticsCenter.java
//执行init的时候执行了IInterceptorGroup的初始化,将interceptor class对象加载到了Warehouse.interceptorsIndex
public synchronized static void init(Context context, ThreadPoolExecutor tpe){
......
......
else if (className.startsWith(ROUTE_ROOT_PAKCAGE + DOT + SDK_NAME + SEPARATOR + SUFFIX_INTERCEPTORS)) {
((IInterceptorGroup) (Class.forName(className).getConstructor().newInstance())).loadInto(Warehouse.interceptorsIndex);
}
}
示例如下:
java
/**
* DO NOT EDIT THIS FILE!!! IT WAS GENERATED BY AROUTER. */
public class ARouter$$Interceptors$$app implements IInterceptorGroup {
@Override
public void loadInto(Map<Integer, Class<? extends IInterceptor>> interceptors) {
interceptors.put(3, LoginInterceptor.class);
}
}
此时Warehouse.interceptorsIndex
中存入了 IInterceptor
的class对象
, 这些拦截器在InterceptorServiceImpl.java
中完成了初始化
java
//InterceptorServiceImpl.java
//遍历Warehouse.interceptorsIndex,执行IInterceptor初始化
for (Map.Entry<Integer, Class<? extends IInterceptor>> entry : Warehouse.interceptorsIndex.entrySet()){
Class<? extends IInterceptor> interceptorClass = entry.getValue();
try{
//反射创建拦截器对象,执行init方法,并将其保存在Warehouse.interceptors中
IInterceptor iInterceptor = interceptorClass.getConstructor().newInstance();
iInterceptor.init(context);
Warehouse.interceptors.add(iInterceptor);
}catch(){
.....
.....
}
}
拦截器生效
Postcard
执行 navigation
时触发
java
//_ARouter.java
protected Object navigation(final Context context, final Postcard postcard, final int requestCode, final NavigationCallback callback) {
......
......
//不是绿色通道,那么需要拦截器的检查
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());
}
});
}
}
执行interceptorService.doInterceptions
, interceptorService
是InterceptorServiceImpl
的实例
java
//InterceptorServiceImpl.java
public void doInterceptions(final Postcard postcard, final InterceptorCallback callback){
// 有拦截器,先执行拦截器相关代码
if (null != Warehouse.interceptors && Warehouse.interceptors.size() > 0) {
LogisticsCenter.executor.execute(new Runnable() {
public void run{
//CancelableCountDownLatch是等待拦截器执行完成或者取消
CancelableCountDownLatch interceptorCounter = new CancelableCountDownLatch(Warehouse.interceptors.size());
//执行拦截器相关代码
_execute(0, interceptorCounter, postcard);
//等待拦截器执行或者超时
interceptorCounter.await(postcard.getTimeout(), TimeUnit.SECONDS);
// 根据拦截器的执行结果,决定后续的执行流程
//拦截器执行超时,后续执行callback.onInterrupt的方法,最终执行NavigationCallback.onInterrupt方法
if (interceptorCounter.getCount() > 0) {
callback.onInterrupt(new HandlerException("The interceptor processing timed out."));
}else if (null != postcard.getTag()){
//如果执行结果中postcard.getTag()不为null,也是最终执行NavigationCallback.onInterrupt方法
callback.onInterrupt(new HandlerException(postcard.getTag().toString()));
}else{
//如果拦截器都不拦截,实际执行_navigation(context, postcard, requestCode, callback);
callback.onContinue(postcard);
}
}
}
}else{
//没有拦截器,则执行callback.onContinue,实际执行_navigation(context, postcard, requestCode, callback);
callback.onContinue(postcard);
}
}
看看_execute(0, interceptorCounter, postcard);
具体执行拦截器的过程
java
//InterceptorServiceImpl.java
private static void _execute(final int index, final CancelableCountDownLatch counter, final Postcard postcard) {
if (index < Warehouse.interceptors.size()) {
//此时的index等于0,也就是从第一个开始取(拦截器还存在优先级的问题)
IInterceptor iInterceptor = Warehouse.interceptors.get(index);
//执行拦截器自身的process方法
iInterceptor.process(postcard, new InterceptorCallback() {
@Override
public void onContinue(Postcard postcard) {
//如果拦截器不拦截,执行结果为onContinue,那么0号拦截器执行完成
counter.countDown();
//启动下一个拦截器的执行(index + 1 )
_execute(index + 1, counter, postcard);
}
@Override
public void onInterrupt(Throwable exception) {
// 如果拦截器执行了拦截,那么取消其他拦截器的等待(counter.cancel()),将postcard的tag赋值
postcard.setTag(null == exception ? new HandlerException("No message.") : exception.getMessage()); // save the exception message for backup.
counter.cancel();
}
})
}
}
如果拦截器执行了拦截过程,null != postcard.getTag()
为true
, 最终执行NavigationCallback.onInterrupt
方法
java
//拦截器执行超时,后续执行callback.onInterrupt的方法,最终执行NavigationCallback.onInterrupt方法
if (interceptorCounter.getCount() > 0) {
callback.onInterrupt(new HandlerException("The interceptor processing timed out."));
}else if (null != postcard.getTag()){
//如果执行结果中postcard.getTag()不为null,也是最终执行NavigationCallback.onInterrupt方法
callback.onInterrupt(new HandlerException(postcard.getTag().toString()));
}else{
//如果拦截器都不拦截,实际执行_navigation(context, postcard, requestCode, callback);
callback.onContinue(postcard);
}
拦截器使用示例
定义拦截器,设置拦截器的内容
java
@Interceptor(name = "login", priority = 3)
class LoginInterceptor : IInterceptor {
override fun init(context: Context?) {
// do init,context == applicaiton
}
override fun process(postcard: Postcard?, callback: InterceptorCallback?) {
if (!LoginManager.isLogin()) {
when (postcard?.path) {
Constants.ARouterPath.MAIN_PATH -> {
callback?.onInterrupt(null)
}
else -> {
callback?.onContinue(postcard)
}
}
} else {
callback?.onContinue(postcard)
}
}
}
触发拦截器后拦截后,执行的业务
kotlin
class LoginNavigationCallbackImpl : NavigationCallback {
override fun onFound(postcard: Postcard?) {
// onFound
}
override fun onLost(postcard: Postcard?) {
}
override fun onArrival(postcard: Postcard?) {
}
override fun onInterrupt(postcard: Postcard?) {
val path = postcard?.path
val bundle = postcard?.extras
val actions = postcard?.action
val flags = postcard?.flags ?: -1
ARouter.getInstance().build(Constants.ARouterPath.LOGIN_PATH)
.withString(LoginActivity.POSTCARD_PATH, path)
.withBundle(LoginActivity.POSTCARD_BUNDLE, bundle)
.withInt(LoginActivity.POSTCARD_FLAGS, flags)
.withString(LoginActivity.POSTCARD_ACTIONS, actions).navigation()
}
}
路由跳转使用拦截器
Postcard
没有设置greenChannel
, 均会触发拦截器的检查
kotlin
fun openMainActivity(context: Context, userId: String) {
ARouter.getInstance().build(MAIN_PATH).withString("userId", userId)
.navigation(context, LoginNavigationCallbackImpl())
}
不需要拦截,可以设置greenChannel
javaARouter.getInstance().build(MAIN_PATH).withString("userId", userId) .greenChannel() .navigation(context, LoginNavigationCallbackImpl())