主要参考文章:
WMRouter源码分析(1)-基本结构分析
WMRouter 整体理解可分4步:这里写了大致流程,细节请结合代码
1、注解部分 - 编译时注解
2、插件源码部分
3、初始化
4、使用
1、注解部分 - 编译时注解
基础篇:带你从头到尾玩转注解
利用javapoet
,根据注解参数,生成java文件;
UriAnnotationProcessor把有RouterUri注解的文件,生成ServiceInit_eb71854fbd69455ef4e0aa026c2e9881.java, UriAnnotationInit_43645645645646456.java
public class ServiceInit_eb71854fbd69455ef4e0aa026c2e9881 {
public static void init() {
ServiceLoader.put(IUriAnnotationInit.class, "com.sankuai.waimai.router.generated.UriAnnotationInit_72565413b8384a4bebb02d352762d60d", com.sankuai.waimai.router.generated.UriAnnotationInit_72565413b8384a4bebb02d352762d60d.class, false);
}
}
public class UriAnnotationInit_72565413b8384a4bebb02d352762d60d implements IUriAnnotationInit {
public void init(UriAnnotationHandler handler) {
handler.register("", "", "/show_toast_handler", new ShowToastHandler(), false);
handler.register("", "", "/login", "com.sankuai.waimai.router.demo.advanced.account.LoginActivity", false);
handler.register("", "", "/account_with_login", "com.sankuai.waimai.router.demo.advanced.account.UserAccountActivity", false, new LoginInterceptor());
}
}
2、插件源码部分:
Gradle Transform API 的基本使用
插件源码 遍历jar文件
及com.sankuai.waimai.router.generated.service
目录下 的 ServiceInit_XXXX 的文件,再使用 asm
生成下面的ServiceLoaderInit.class文件
public class ServiceLoaderInit {
public static void init() {
ServiceInit_aea7f96d0419b507d9b0ef471913b2f5.init();
ServiceInit_f3649d9f5ff15a62b844e64ca8434259.init();
ServiceInit_eb71854fbd69455ef4e0aa026c2e9881.init();
ServiceInit_b57118238b4f9112ddd862e55789c834.init();
ServiceInit_f1e07218f6691f962a9f674eb5b4b8bd.init();
ServiceInit_4268a3e74040533ba48f2e1679155468.init();
ServiceInit_e694d982fb5d7a3a8c6b7085829e74a6.init();
ServiceInit_ee5f6404731417fe1433da40fd3c9708.init();
ServiceInit_9482ef47a8cf887ff1dc4bf705d5fc0a.init();
ServiceInit_36ed390bf4b81a8381d45028b37cc645.init();
}
}
3、初始化:
// application 中初始化
Router.init(rootHandler);
new AsyncTask<Void, Void, Void>() { // 懒加载后台初始化(可选)
@Override
protected Void doInBackground(Void... voids) {
Router.lazyInit();
return null;
}
}.execute();
//Router.java
public static void lazyInit() {
ServiceLoader.lazyInit();
getRootHandler().lazyInit();
}
ServiceLoader.lazyInit() 中 使用反射 调用 插件生成的ServiceLoaderInit.init()
,加载所有服务; getRootHandler().lazyInit();从前面加载的服务中查找 有关服务,调用ServiceInit_XXXX的init(),继而调用UriAnnotationInit_72565413b8384a4bebb02d352762d60d.init(UriAnnotationHandler handler),注册各种handler 进 roothandler 中的各种分类handler中;
public DefaultRootUriHandler(Context context,
@Nullable String defaultScheme, @Nullable String defaultHost) {
super(context);
mPageAnnotationHandler = createPageAnnotationHandler();
mUriAnnotationHandler = createUriAnnotationHandler(defaultScheme, defaultHost);
mRegexAnnotationHandler = createRegexAnnotationHandler();
// 按优先级排序,数字越大越先执行
// 处理RouterPage注解定义的内部页面跳转,如果注解没定义,直接结束分发
addChildHandler(mPageAnnotationHandler, 300);
// 处理RouterUri注解定义的URI跳转,如果注解没定义,继续分发到后面的Handler
addChildHandler(mUriAnnotationHandler, 200);
// 处理RouterRegex注解定义的正则匹配
addChildHandler(mRegexAnnotationHandler, 100);
// 添加其他用户自定义Handler...
// 都没有处理,则尝试使用默认的StartUriHandler直接启动Uri
addChildHandler(new StartUriHandler(), -100);
// 全局OnCompleteListener,用于输出跳转失败提示信息
setGlobalOnCompleteListener(DefaultOnCompleteListener.INSTANCE);
}
2、使用:
Router.startUri(uriRequest);
从roothandler 中各个分handler 中查找能处理 请求的 handler。
至于查找过程则是 遍历+ 递归
网友评论