Aroute优点:
1 :支持解析标准得URl进行跳转,并且自动注入参数到目标页面。
2 : 支持多模块工程使用。
3 :支持依赖注入,传递数据。
4 :支持多个拦截器,自定义拦截顺序。
5 : 支持MultiDex
6 : 支持获取service和fragment等。
Aroute原理
1 : 路由跳转,隐式Intent,维护action在多个模块繁琐。显示Intent,需要目标Class。各个模块需要引用Arouter.把所有的符合要求class获取和存储。通过路由找到目标class。
2 : 获取Service ,把所有service存到Arouter中,通过路由找到目标Service(provider)
3 : 依赖注入, 编译时期解析注解,创建需要赋值的class类 . 运行时期 通过类名反射创建对象,直接调用赋值。
Aroute模块
分为annotation api compiler app 和 moudle
![](https://img.haomeiwen.com/i1501988/cbab2610c974e3d1.png)
路由跳转
1 : ArouterProcessor : 负责生成路由得root和group和provider的class
2 : AutowiredProcessor : 负责解析生成传输数据得解析。
3 : 如果使用插件,自动注册。 使用插件防止路由信息太多,加载较慢,内存占用较大,anr等问题。
4 :初始化。 遍历本地符合得class文件。
final CountDownLatch countDownLatch = new CountDownLatch(paths.size());
for (String path : paths) {
DefaultPoolExecutor.getInstance().execute(new Runnable() {
@Override
public void run() {
DexFile dexFile = null;
try {
if (path.endsWith(EXTRACTIED_SUFFIX)) {
dexFile = DexFile.loadDex(path, path + ".tmp", 0);
} else {
dexFile = new DexFile(path);
}
Enumeration<String> dexEntries = dexFile.entries();
while (dexEntries.hasMoreElements()) {
String className = dexEntries.nextElement();
if (className.startsWith(packageName)) {
classNames.add(className);
}
}
5,6 :传入一个map去生成得class中加载所有得group。
static Map<String,Class<? extends IRouteGroup>> groupsIndex = new HashMap<>();
Set<String> routerMap = ClassUtils.getFileNameByPackageName(context, Consts.ROUTE_ROOT_PACKAGE);
for (String className : routerMap) {
if (className.startsWith(Consts.ROUTE_ROOT_PACKAGE + ".ARouter_Root")) {
((IRouteRoot) Class.forName(className).getConstructor().newInstance()).loadInto(WareHouse.groupsIndex);
} else if (className.startsWith(Consts.ROUTE_ROOT_PACKAGE + ".ARouter_Provider")) {
((IProviderGroup) (Class.forName(className).getConstructor().newInstance())).loadInto(WareHouse.providerIndex);
}
}
7 :路由跳转,通过传入得group,从刚才得map中得到组得class,反射创建该对象。
8,9 : 该对象再通过map把数据加载存储到wareHouse
static Map<String, RouteMeta> routeMetaMap = new HashMap<>();
10 :warehouse 通过path得到RouteMeta,RouteMeta中包含了跳转所需要得class,类型,和参数,优先级等。如果是provider,则有provider等信息。
public synchronized static void completion(PostCard postCard){
if(null == postCard){
throw new RuntimeException("no postCard");
}
RouteMeta routeMeta = WareHouse.routeMetaMap.get(postCard.getPath());
if(null == routeMeta){
if(!WareHouse.groupsIndex.containsKey(postCard.getGroup())){
throw new RuntimeException("no postcard");
}else {
addRouteGroupDynamic(postCard.getGroup(),null);
}
completion(postCard);
}else {
postCard.setDestination(routeMeta.getDestination());
postCard.setType(routeMeta.getType());
postCard.setPriority(routeMeta.getPriority());
switch (routeMeta.getType()){
case PROVIDER:
Class<? extends IProvider> providerMeta = (Class<? extends IProvider>) routeMeta.getDestination();
IProvider instance = WareHouse.providerMap.get(providerMeta);
if(instance == null){
IProvider provider;
try {
provider = providerMeta.getConstructor().newInstance();
provider.init(context);
WareHouse.providerMap.put(providerMeta,provider);
instance = provider;
}catch (Exception e){
e.printStackTrace();
11 :比如是activity类型,直接跳转。 如果是provider,拿到注解得那个provider对象,就可以使用provider中得方法。
protected Object navigation(final Context context, final PostCard postCard, final NavigationCallback navigationCallback) {
postCard.setContext(context == null ? mContext : context);
LogisticsCenter.completion(postCard);
switch (postCard.getType()) {
case ACTIVITY:
final Intent intent = new Intent(postCard.getContext(), postCard.getDestination());
intent.putExtras(postCard.getBundle());
if (!(postCard.getContext() instanceof Activity)) {
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
}
runInMainThread(new Runnable() {
@Override
public void run() {
postCard.getContext().startActivity(intent);
}
});
break;
case PROVIDER:
return postCard.getProvider();
}
return null;
}
依赖注入Autowired
![](https://img.haomeiwen.com/i1501988/28c72e1900c927ce.png)
1 .2 :都是第一幅图的逻辑。
3 :传递数据,通过bundle写入数据,intent传递。
4 : Arouter.getInstance().inject(this) 通过this类名得到生成的类的class。创建对象,把数据绑定到this上。
private void doinject(Object object,Class parent){
Class clazz = parent == null ? object.getClass() : parent;
try {
ISyringe iSyringe = (ISyringe) Class.forName(clazz.getName()+ Consts.SUFFIX_AUTOWIRED).getConstructor().newInstance();
if(iSyringe != null){
iSyringe.inject(object);
}
Class superclass = clazz.getSuperclass();
if(null != superclass && !superclass.getName().startsWith("android")) {
doinject(object, superclass);
}
} catch (Exception e) {
e.printStackTrace();
}
}
ArouterProcessor 路由跳转/获取服务
收集注解存到groupMap<group,routeMeta>():
for (Element element : routeElements) {
TypeMirror tm = element.asType();
Route route = element.getAnnotation(Route.class);
RouteMeta routeMeta = null;
if (types.isSubtype(tm, typeActivity)) {
routeMeta = new RouteMeta(route, element, RouteType.ACTIVITY);
} else if (types.isSubtype(tm, typeProvider)) {
routeMeta = new RouteMeta(route, element, RouteType.PROVIDER);
} else if (types.isSubtype(tm, typeService)) {
routeMeta = new RouteMeta(route, element, RouteType.SERVICE);
}
categories(routeMeta);
}
生成class
switch (routeMeta.getType()) {
case PROVIDER:
TypeElement rawType = (TypeElement) routeMeta.getRawType();
List<? extends TypeMirror> interfaces = rawType.getInterfaces();
for (TypeMirror tm : interfaces) {
if (types.isSameType(tm, typeProvider)) {
loadIntoMethodofProviderBuilder.addStatement("providers.put($S,$T.build($T." + routeMeta.getType() + ",$T.class,$S,$S," + routeMeta.getPriority() + "))",
routeMeta.getRawType().toString(),
routeMetaCn,
routeMetaCn,
className,
routeMeta.getPath(),
routeMeta.getGroup());
} else if (types.isSubtype(tm, typeProvider)) {
loadIntoMethodofProviderBuilder.addStatement("providers.put($S,$T.build($T." + routeMeta.getType() + ",$T.class,$S,$S," + routeMeta.getPriority() + "))",
tm.toString(),
routeMetaCn,
routeTypeCn,
className,
routeMeta.getPath(),
routeMeta.getGroup());
}
}
break;
default:
break;
生成provider,为什么要区分types.isSameType和types.isSubType? -- 接口隔离
例1 : B moudle 定义一个带路由的SerVice, A moudle 没有依赖B , 现在A想通过路由拿到这个SerVice。 路由拿到了,但是没办法使用这个对象。
解决: 定义一个公共的BaseService,定义公共方法,A,B都依赖这个Service,当A拿到B这个SerVice对象的时候,使用BaseService去接收和使用。
例2 : AppMoudle 依赖Amoudle 现在Amoudle想拿到AppMoudle中的数据, 平时我们写个方法跳转转递,现在只需要在Amoudle中定义一个Service。AppMoudle实现它,在AMoudle中,主动获取就可以了。
生成group
routeMeta.getPath(),
routeMetaCn,
routeTypeCn,
className,
routeMeta.getPath().toLowerCase(),
routeMeta.getGroup().toLowerCase());
}
//生成groups
String groupFileName = Consts.NAME_OF_GROUP + groupName;
JavaFile.builder(Consts.PACKAGE_OF_GENERATE_FILE, TypeSpec.classBuilder(groupFileName)
.addSuperinterface(ClassName.get(typeGroup))
.addModifiers(Modifier.PUBLIC)
.addMethod(loadInfoMethodOfGroupBuilder.build())
.build()).build().writeTo(filer);
rootMap.put(groupName, groupFileName);
}
if (MapUtils.isNotEmpty(rootMap)) {
for (Map.Entry<String, String> entry : rootMap.entrySet()) {
loadIntoMethodRootBuilder.addStatement("routers.put($S,$T.class)", entry.getKey(), ClassName.get(Consts.PACKAGE_OF_GENERATE_FILE, entry.getValue()));
}
}
AutoWiredProcessor 参数依赖注入
收集Map
Map<TypeElement, List<Element>> parentAndChild = new HashMap<>();
生成class
1 支持provider的成员变量。
2 支持bundle基本类型,序列化对象传递。
3 支持object对象传递和解析。解析object对象使用serializationService
解析如下:
substitute.dou = substitute.getArguments().getDouble("dou", substitute.dou);
substitute.ser = (com.alibaba.android.arouter.demo.service.model.TestSerializable) substitute.getArguments().getSerializable("ser");
substitute.pac = substitute.getArguments().getParcelable("pac");
if (null != serializationService) {
substitute.objList = serializationService.parseObject(substitute.getArguments().getString("objList"),
new com.alibaba.android.arouter.facade.model.TypeWrapper<List<TestObj>>(){}.getType());
} else {
Log.e("ARouter::", "You want automatic inject the field 'objList' in class 'BlankFragment' , then you should implement 'SerializationService' to support object auto inject!");
}
对象传递如下:
public Postcard withObject(@Nullable String key, @Nullable Object value) {
serializationService = ARouter.getInstance().navigation(SerializationService.class);
mBundle.putString(key, serializationService.object2Json(value));
return this;
}
5 获取service的两种方式:
public void inject(Object object) {
// AutoWiredServiceImpl navigation1 = (AutoWiredServiceImpl) Arouter.getInstance().navigation(AutoWireService.class);
AutoWireService navigation = (AutoWireService) Arouter.getInstance().build("/lisi/service/autowired").navigation();
navigation.autoWire(object);
}
注入- 绑定数据给当前对象
Arouter.getInstance().inject(this);
总结
Arouter 收集数据,收集class,都存储在对象中,再依据路由调用,获取数据,class,分发给各个moudle。类似于加工平台和中转站。
Arouter 几个优点,互不依赖的moudle相互跳转,传递数据,支持Uri,支持优先级,这几个优点利于组件开发,高内聚,低耦合。
网友评论