通过Route注解去探究如何实现路由跳转 - Xiasm/EasyRouter GitHub Wiki
上节大概了解了根据路由地址去实现跳转的方式,只是做个启发,这节我们就详细介绍一下实现的细节。
简单讲,要通过Route注解生成我们的路由表,首先第一步需要定义注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.CLASS)
public @interface Route {
/**
* 路由的路径
* @return
*/
String path();
/**
* 将路由节点进行分组,可以实现动态加载
* @return
*/
String group() default "";
}
这里看到Route注解里有path和group,这便是仿照ARouter对路由进行分组。因为当项目变得越来越大庞大的时候,为了便于管理和减小首次加载路由表过于耗时的问题,我们对所有的路由进行分组。在ARouter中会要求路由地址至少需要两级,如"/xx/xx",一个模块下可以有多个分组。这里我们就将路由地址定为必须大于等于两级,其中第一级是group。如app module下的路由注解:
@Route(path = "/main/main")
public class MainActivity extends AppCompatActivity {}
@Route(path = "/main/main2")
public class Main2Activity extends AppCompatActivity {}
@Route(path = "/show/info")
public class ShowActivity extends AppCompatActivity {}
在项目编译的时候,我们将会通过apt生成EaseRouter_Root_app文件和EaseRouter_Group_main、EEaseRouter_Group_show等文件,EaseRouter_Root_app文件对应于app module,里面记录着本module下所有的分组信息,EaseRouter_Group_main、EaseRouter_Group_show文件分别记载着app module下每个分组的所有路由地址和ActivityClass映射信息。
本demo在编译的时候会生成类如下所示,先不要管这些类是怎么生成的,仔细看类的内容
public class EaseRouter_Root_app implements IRouteRoot {
@Override
public void loadInto(Map<String, Class<? extends IRouteGroup>> routes) {
routes.put("main", EaseRouter_Group_main.class);
routes.put("show", EaseRouter_Group_show.class);
}
}
public class EaseRouter_Group_main implements IRouteGroup {
@Override
public void loadInto(Map<String, RouteMeta> atlas) {
atlas.put("/main/main",RouteMeta.build(RouteMeta.Type.ACTIVITY,Main2\Activity.class,"/main/main","main"));
atlas.put("/main/main2",RouteMeta.build(RouteMeta.Type.ACTIVITY,Main2\Activity.class,"/main/main2","main"));
}
}
public class EaseRouter_Group_show implements IRouteGroup {
@Override
public void loadInto(Map<String, RouteMeta> atlas) {
atlas.put("/show/info",RouteMeta.build(RouteMeta.Type.ACTIVITY,ShowActivity.class,"/show/info","show"));
}
}
大家会看到生成的类分别实现了IRouteRoot和IRouteGroup接口,并且实现了loadInto()方法,而loadInto方法通过传入一个特定类型的map就能把分组信息放入map里。这两个接口是干嘛的我们先搁置,继续往下看
如果我们在login_module中想启动app_module中的MainActivity类,首先,我们已知MainActivity类的路由地址是"/main/main",第一个"/main"代表分组名,那么我们岂不是可以像下面这样调用去得到MainActivity类文件,然后startActivity。这里的RouteMeta只是存有Activity class文件的封装类,先不用理会。
public void test() {
EaseRouter_Root_app rootApp = new EaseRouter_Root_app();
HashMap<String, Class<? extends IRouteGroup>> rootMap = new HashMap<>();
rootApp.loadInto(rootMap);
//得到/main分组
Class<? extends IRouteGroup> aClass = rootMap.get("main");
try {
HashMap<String, RouteMeta> groupMap = new HashMap<>();
aClass.newInstance().loadInto(groupMap);
//得到MainActivity
RouteMeta main = groupMap.get("/main/main");
Class<?> mainActivityClass = main.getDestination();
Intent intent = new Intent(this, mainActivityClass);
startActivity(intent);
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
可以看到,只要有了这些实现了IRouteRoot和IRouteGroup的类文件,我们便能轻易的启动其他module的Activity了。其实这就是路由跳转的原理,这些类文件,我们可以约定好之后,在代码的编写过程中自己手动实现,也可以通过apt生成。作为一个框架,当然是自动解析Route注解然后生成这些类文件更好了。要想自动生成这些路由地址与Activity的映射关系,那么便要了解apt和javapoet了。