aleyn97 / router

Routing framework for Android.
Apache License 2.0
99 stars 11 forks source link

有办法优化一下编译流程吗?目前即使未修改任何代码,每次运行 dexBuilderDebug 都会耗时很久 #6

Closed xiaoyvyv closed 4 months ago

xiaoyvyv commented 11 months ago

项目目前每次运行都会耗时将近一分钟(即使不修改代码的情况下),都做了全量的classes处理,能优化一下吗?

图片 图片

aleyn97 commented 11 months ago

项目目前每次运行都会耗时将近一分钟(即使不修改代码的情况下),都做了全量的classes处理,能优化一下吗?

图片 图片

已经在寻找方案了, AsmClassVisitorFactory 无法满足现在的需求,不得已才用的自定义 TASK 全量处理。

xiaoyvyv commented 8 months ago

Hi,请问这个有解决方案了吗?

xiaoyvyv commented 7 months ago

最近Fork仓库大致看了一下,发现了耗时的原因

因为你扫描修改插桩的类是在你的 router 模块下,这个是作为依赖到项目的,所以你 toTransform 只能设置 Scope 为 ALL,这样将会导致很严重的耗时。因为公司项目一般很大,依赖将非常多,全量扫描的生成的 classes.jar 能达到 100M+,这里有很大的优化空间。

优化方案:

  1. 将 toTransform 的 Scope 设置为 PROJECT
  2. 由于 Scope 设置为 PROJECT 仅处理项目内的 class,将无法修改依赖的相关 jar 的类,所以需要调整一下。将 router 模块内的插桩类中的的几个初始化方法抽象出来,比如 IRouterGenerate
@Keep
interface IRouterGenerate {
    @Keep
    fun injectAutowired(target: Any?)

    @Keep
    fun initModuleRouter()

    @Keep
    fun registerIntercept()

    @Keep
    fun registerAllInitializer()
}

然后由插件再 app 模块生成一个位于 generated 目录下的占位插桩类 RouterGenerateHolder,然后继承 IRouterGenerate,这个类属于 PROJECT 范围内,可以被扫描到并修改。

androidComponents.onVariants { variant ->
            if (isApp) {
                val addSourceTaskProvider = project.tasks.register(
                    "${variant.name}RouterStubClass",
                    RouterStubClassTask::class.java
                )

                @Suppress("UnstableApiUsage")
                variant.sources.java!!.addGeneratedSourceDirectory(
                    addSourceTaskProvider,
                    RouterStubClassTask::outputFolder
                )
            }
}
  1. 然后 router 模块内 LRouterGenerate.kt 相关的方法,直接去加载 RouterGenerateHolder 的单例,并调用对应方法即可。
package com.aleyn.router.inject

import androidx.annotation.Keep

private val instance: IRouterGenerate by lazy {
    Class.forName("com.router.RouterGenerateHolder")
        .getDeclaredConstructor()
        .newInstance() as IRouterGenerate
}

@Keep
internal fun injectAutowired(target: Any?) {
    instance.injectAutowired(target)
}

@Keep
internal fun initModuleRouter() {
    instance.initModuleRouter()
}

@Keep
internal fun registerIntercept() {
    instance.registerIntercept()
}

@Keep
internal fun registerAllInitializer() {
    instance.registerAllInitializer()
}
  1. 还有一点,由于 toTransform 设置 Scope 为 PROJECT,还需要修改 LRouterClassTask 的注入,需要所有 application 和 library 模块都要启用,不单只是 application 模块。

基本上就可以大幅优化编译时间了

xiaoyvyv commented 7 months ago

可以看下我 fork 后优化的

plugin 模块

RouterPlugin.kt LRouterClassTask.kt RouterStubClassTask.kt

router 模块

LRouterGenerate.kt IRouterGenerate.kt AutowiredInstructAdapter.kt loadstorevarIndex 调整了一下,因为修改的不是静态方法了。

aleyn97 commented 6 months ago

@xiaoyvyv 不好意思,过了年这段时间一直在忙,你的方案我看了,最开始其实考虑过在APP模块下做插入,当时为了尽量的减少反射,放到 Router 模块了,现在确实太影响编译速度了,我把你修改的,整理下先发个版本出来。

然后我试着用 transformClassesWith 方式处理编译速度会更快,会直接走增量更新。有一点问题就是 APP 主模块下不能写与LRouter 相关的类文件,全都要放到子模块,等我再想办法把这个问题解决了,再发布 transformClassesWith 方式。

aleyn97 commented 6 months ago

@xiaoyvyv 可以试下 1.0.6