给 TheRouter 提个 PR

我正在参加「掘金·启航计划」

1、背景

近期在探索项目端架构升级,遇到不少历史遗留问题,比较典型的就是模块耦合、动态路由配置表冗余。同时,也在探索如何使用智能策略提供更好的基础体验,用好的技术方案做一些既要又要还要(老板们都是这么想)的事情。

无意看到了 TheRouter,发现它的设计思路能解决目前项目所面临的问题,作者对端侧动态能力的发展方向上与我的思路不谋而合(端+云+智能策略),看完还是有点小兴奋。

于是,立马把代码拉下来看看,结果异常了~

2、问题

在拉取master分支并运行后,发现如下问题:

image.png

3、分析

3-1 表面原因

从错误提示上看异常类在/build/generated/source/kapt/debug/文件中,说明出问题的类是kapt自动生成的代码。

再看看Test3#createTest5这个函数实现,基本能确定:kapt自动生成的类,在调用Test3#createTest5时少了一个参数。

image.png

3-2 APT 逻辑

1、首先需要找到生成问题类的函数, 通过查找确定TheRouterAnnotationProcessor#genJavaFile中生存了问题类(以下逻辑有删减):

private fun genJavaFile(
    pageList: ArrayList<ServiceProviderItem>,
    flowTaskList: MutableList<FlowTaskItem>,
    actionInterceptorList: MutableList<ActionInterceptorItem>
) {
    var ps: PrintStream? = null
    try {
            ......
            ps.println(") {")
            ps.println("\t\t\t//type verification during compilation prevents the actual return type of the method from mismatching with the return type declared by the annotation")

            if (serviceProviderItem.isMethod) {
                ps.print(String.format("\t\t\t%s returnType = %s.%s(", serviceProviderItem.returnType,serviceProviderItem.className,serviceProviderItem.methodName))
            } 
            ......
            for (count in serviceProviderItem.params.indices) {
                if (!serviceProviderItem.params[count].trim { it <= ' ' }.isEmpty()) {
                    //参数强转
                    ps.print(String.format(Locale.getDefault(),"(%s) params[%d]",serviceProviderItem.params[count],count))
                    if (count != serviceProviderItem.params.size - 1) {
                        ps.print(", ")
                    }
                }
            }
            ps.println(");")
            ps.println("\t\t\tobj = (T) returnType;")
            ps.print("\t\t} else ")
        }
        ...
}

从上述逻辑可以了解到:serviceProviderItem.params就是最终的参数表。

2、再断点调试发现createTest5的参数理论上有两个:StringContext,然而serviceProviderItem.params中却只有一个, 所以问题基本能定位是serviceProviderItem.params的赋值问题了。

image.png

3、serviceProviderItem.params 是在这个函数TheRouterAnnotationProcessor#handleMethodServiceProviderItem中赋值的,通过解析注解中的信息赋值给 params 。

image.png
按照代码逻辑,这里 temp 的值应该是“@com.therouter.inject.ServiceProvider(params=java.lang.String,android.content.Context”但是这里实际值是"@com.therouter.inject.ServiceProvider(params=java.lang.String",所以这里看起来是本地代码与项目代码不一致。

再看 commit 记录这个问题在之前涛哥有专门修过,少了一个空格符。

image.png
所以本地代码应该是 OK 的。

4、问题解决

1、把 apt 模块改成本地依赖再编译确实可以了。

image.png
问题是解决了,但是看注解的解析过程还是比较费劲且不太优雅。

5、优化一下

1、再看看解析上能怎么能优化一下,梳理一下TheRouterAnnotationProcessor#handleMethodServiceProviderItem的核心逻辑。

image.png
使用了比较多indexlength,解析逻辑相对复杂不太好理解。

2、回到要解析的字符串———“@com.therouter.inject.ServiceProvider(params=java.lang.String,android.content.Context,returnType=com.therouter.inject.ServiceProvider)”,其实可以用正则直接找出对应的 Key-Value 赋值即可,可以增加代码可读性,同时解析逻辑复用度也相对高些:

image.png

6、提个PR

github.com/HuolalaTech…

7、最后一点建议

最后,给 TheRouter 所提的动态路由能力提点建议:动态路由除了关注动态能力外,前期也建议做好配置热度跟踪。随着业务的迭代,如果没有对应的热度统计,后期大量的冗余配置会对配置的运行加载稳定性造成负面影响,同时过大的路由表会延长匹配时间进而影响页面打开速度等。同时,路由本身可以理解为APP运行的中枢神经,随着配置的增多,后期迁移、改动或替换的风险较高,所以应想办法在前期做好统计管理,避免配置冗余。

© 版权声明
THE END
喜欢就支持一下吧
点赞0

Warning: mysqli_query(): (HY000/3): Error writing file '/tmp/MYyeEo4T' (Errcode: 28 - No space left on device) in /www/wwwroot/583.cn/wp-includes/class-wpdb.php on line 2345
admin的头像-五八三
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

图形验证码
取消
昵称代码图片