美文网首页
WMRouter阅读笔记

WMRouter阅读笔记

作者: 仔强小狐狸 | 来源:发表于2019-05-09 15:28 被阅读0次

主要参考文章:
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。
至于查找过程则是 遍历+ 递归

相关文章

网友评论

      本文标题:WMRouter阅读笔记

      本文链接:https://www.haomeiwen.com/subject/uimwoqtx.html