我正在参加「启航计划」

1、背景

近期在探究项目端架构晋级,遇到不少前史遗留问题,比较典型的便是模块耦合、动态路由装备表冗余。一起,也在探究如何运用智能战略提供更好的根底体验,用好的技术计划做一些既要又要还要(老板们都是这么想)的工作。

无意看到了 TheRouter,发现它的规划思路能处理目前项目所面对的问题,作者对端侧动态才能的发展方向上与我的思路不约而同(端+云+智能战略),看完还是有点小兴奋。

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

2、问题

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

给 TheRouter 提个 PR

3、分析

3-1 外表原因

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

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

给 TheRouter 提个 PR

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的赋值问题了。

给 TheRouter 提个 PR

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

给 TheRouter 提个 PR
依照代码逻辑,这儿 temp 的值应该是“@com.therouter.inject.ServiceProvider(params=java.lang.String,android.content.Context”可是这儿实际值是"@com.therouter.inject.ServiceProvider(params=java.lang.String",所以这儿看起来是本地代码与项目代码不一致。

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

给 TheRouter 提个 PR
所以本地代码应该是 OK 的。

4、问题处理

1、把 apt 模块改成本地依赖再编译确实能够了,或许换成最新的版本也是OK的。

给 TheRouter 提个 PR
问题是处理了,可是看注解的解析过程还是比较费劲且不太优雅。

5、优化一下

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

给 TheRouter 提个 PR
运用了比较多indexlength,解析逻辑相对杂乱不太好理解。

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

给 TheRouter 提个 PR

6、提个PR

github.com/HuolalaTech…

7、最终一点主张

最终,给 TheRouter 所提的动态路由才能提点主张:动态路由除了重视动态才能外,前期也主张做好装备热度盯梢。跟着业务的迭代,假如没有对应的热度计算,后期大量的冗余装备会对装备的运转加载稳定性造成负面影响,一起过大的路由表会延伸匹配时刻进而影响页面翻开速度等。一起,路由自身能够理解为APP运转的中枢神经,跟着装备的增多,后期迁移、改动或替换的风险较高,所以应想办法在前期做好计算办理,防止装备冗余。