ARouter解析
目录
准备工作
因为ARouter使用ASM字节码注入,初始化流程涉及到的关键地方,源码是看不到的,所以需要找到生成后的class或jar。
查看build log
ARouter::Register >>> Insert register code to file /ARouter/app/build/intermediates/transforms/com.alibaba.arouter/debug/41.jar
ARouter::Register >>> Insert init code to class >> com/alibaba/android/arouter/core/LogisticsCenter.class
反编译41.jar
使用Java Decompiler反编译41.jar,源码中LogisticsCenter
的loadRouterMap()方法:
private static void loadRouterMap() {
registerByPlugin = false;
//auto generate register code by gradle plugin: arouter-auto-register
// looks like below:
// registerRouteRoot(new ARouter..Root..modulejava());
// registerRouteRoot(new ARouter..Root..modulekotlin());
}
字节码注入之后是:
private static void loadRouterMap() {
registerByPlugin = false;
register("com.alibaba.android.arouter.routes.ARouter$$Root$$modulejava");
register("com.alibaba.android.arouter.routes.ARouter$$Root$$modulekotlin");
register("com.alibaba.android.arouter.routes.ARouter$$Root$$arouterapi");
register("com.alibaba.android.arouter.routes.ARouter$$Root$$app");
register("com.alibaba.android.arouter.routes.ARouter$$Interceptors$$modulejava");
register("com.alibaba.android.arouter.routes.ARouter$$Interceptors$$app");
register("com.alibaba.android.arouter.routes.ARouter$$Providers$$modulejava");
register("com.alibaba.android.arouter.routes.ARouter$$Providers$$modulekotlin");
register("com.alibaba.android.arouter.routes.ARouter$$Providers$$arouterapi");
register("com.alibaba.android.arouter.routes.ARouter$$Providers$$app");
}
原理解析:
首先com.alibaba.arouter
插件配置三个接口:
- IRouteRoot
- IInterceptorGroup
- IProviderGroup
def transformImpl = new RegisterTransform(project)
ArrayList<ScanSetting> list = new ArrayList<>(3)
list.add(new ScanSetting('IRouteRoot'))
list.add(new ScanSetting('IInterceptorGroup'))
list.add(new ScanSetting('IProviderGroup'))
RegisterTransform.registerList = list
//register this plugin
android.registerTransform(transformImpl)
在所有模块的com/alibaba/android/arouter/routes/包下,找到实现了上述三个接口的类,将类名作为参数传递给register,再插入到loadRouterMap()方法中,形成了如上的样子。
注册
注册分为3种:
- IRouteRoot
- IProviderGroup
- IInterceptorGroup
private static void register(String className) {
if (!TextUtils.isEmpty(className)) {
try {
Class<?> clazz = Class.forName(className);
Object obj = clazz.getConstructor().newInstance();
if (obj instanceof IRouteRoot) {
registerRouteRoot((IRouteRoot) obj);
} else if (obj instanceof IProviderGroup) {
registerProvider((IProviderGroup) obj);
} else if (obj instanceof IInterceptorGroup) {
registerInterceptor((IInterceptorGroup) obj);
} else {
logger.info(TAG, "register failed, class name: " + className
+ " should implements one of IRouteRoot/IProviderGroup/IInterceptorGroup.");
}
} catch (Exception e) {
logger.error(TAG,"register class error:" + className);
}
}
}
注册完成的信息分别放在:
- Warehouse.groupsIndex
- Warehouse.providersIndex
- Warehouse.interceptorsIndex
跳转
主要原理是使用注解生成path和Class
/**
* DO NOT EDIT THIS FILE!!! IT WAS GENERATED BY AROUTER. */
public class ARouter$$Group$$module implements IRouteGroup {
@Override
public void loadInto(Map<String, RouteMeta> atlas) {
atlas.put("/module/1", RouteMeta.build(RouteType.ACTIVITY, TestModuleActivity.class, "/module/1", "module", null, -1, -2147483648));
atlas.put("/module/3", RouteMeta.build(RouteType.ACTIVITY, TestModule3Activity.class, "/module/3", "module", null, -1, -2147483648));
}
}
调用api:
ARouter.getInstance().build("/module/1")
.withString("key1", "value1")
.navigation();
使用Bundle传递参数,然后在_ARouter类跳转:
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
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;
default:
return null;
}
return null;
}
startActivityForResult
ARouter.getInstance().build("/test/activity2").navigation(this, 666);
旧版转场动画
ARouter.getInstance()
.build("/test/activity2")
.withTransition(R.anim.slide_in_bottom, R.anim.slide_out_bottom)
.navigation(this);
新版转场动画
if (Build.VERSION.SDK_INT >= 16) {
ActivityOptionsCompat compat = ActivityOptionsCompat.
makeScaleUpAnimation(v, v.getWidth() / 2, v.getHeight() / 2, 0, 0);
ARouter.getInstance()
.build("/test/activity2")
.withOptionsCompat(compat)
.navigation();
} else {
Toast.makeText(this, "API < 16,不支持新版本动画", Toast.LENGTH_SHORT).show();
}
拦截器
使用@Interceptor注解,会在对应module下生成:
/**
* 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(7, Test1Interceptor.class);
}
}
对于实现了IProvider的接口,会生成PROVIDER类型的RouteMeta:
/**
* DO NOT EDIT THIS FILE!!! IT WAS GENERATED BY AROUTER. */
public class ARouter$$Group$$arouter implements IRouteGroup {
@Override
public void loadInto(Map<String, RouteMeta> atlas) {
atlas.put("/arouter/service/autowired", RouteMeta.build(RouteType.PROVIDER, AutowiredServiceImpl.class, "/arouter/service/autowired", "arouter", null, -1, -2147483648));
atlas.put("/arouter/service/interceptor", RouteMeta.build(RouteType.PROVIDER, InterceptorServiceImpl.class, "/arouter/service/interceptor", "arouter", null, -1, -2147483648));
}
}
_ARouter
触发初始化:
static void afterInit() {
// Trigger interceptor init, use byName.
interceptorService = (InterceptorService) ARouter.getInstance().build("/arouter/service/interceptor").navigation();
}
定位到InterceptorServiceImpl类,通过反射构造实例,并调用init方法。此时所有带@Interceptor注解的类将初始化。
方法调用
对于实现了IProvider的类,打上@Route注解,会生成PROVIDER类型的RouteMeta:
public interface HelloService extends IProvider {
void sayHello(String name);
}
/**
* DO NOT EDIT THIS FILE!!! IT WAS GENERATED BY AROUTER. */
public class ARouter$$Group$$yourservicegroupname implements IRouteGroup {
@Override
public void loadInto(Map<String, RouteMeta> atlas) {
atlas.put("/yourservicegroupname/hello", RouteMeta.build(RouteType.PROVIDER, HelloServiceImpl.class, "/yourservicegroupname/hello", "yourservicegroupname", null, -1, -2147483648));
atlas.put("/yourservicegroupname/json", RouteMeta.build(RouteType.PROVIDER, JsonServiceImpl.class, "/yourservicegroupname/json", "yourservicegroupname", null, -1, -2147483648));
atlas.put("/yourservicegroupname/single", RouteMeta.build(RouteType.PROVIDER, SingleService.class, "/yourservicegroupname/single", "yourservicegroupname", null, -1, -2147483648));
}
}
通过路径定位到类,实例化之后调用其方法:
((HelloService) ARouter.getInstance().build("/yourservicegroupname/hello").navigation()).sayHello("mike");