PAYATHON 2026

Android Studio Ladybug(2024.2.2) 导入和构建项目耗时过长

技术老齐

结论

增加 Android Studio 堆内存,或者启用 org.gradle.parallel、org.gradle.daemon,通常不能直接解决导入缓慢的问题。首先要确认时间花在哪个阶段:

  1. Gradle Sync 与依赖解析;
  2. Gradle 配置阶段;
  3. Kotlin/KAPT、资源处理、Dex 或原生构建;
  4. Android Studio 索引;
  5. 网络、磁盘或杀毒软件扫描。

根据现有配置,建议先检查动态版本依赖、JitPack 等远程仓库、第三方 Gradle 插件、KAPT,以及首次下载的大型 SDK。尤其要注意这项依赖:

implementation 'com.facebook.android:facebook-android-sdk:[8,9)'

它使用了动态版本范围。Gradle 为了确定实际版本,可能反复访问仓库并检查元数据。多个 com.github.* 依赖通常还会查询 JitPack,网络不稳定时,Gradle Sync 会明显变慢。hypersdk.plugin、Firebase Crashlytics、Google Services 等插件也会增加配置时间,因此不能只看依赖数量来判断瓶颈。

先确定到底慢在哪里

不要反复执行 Clean Build。它会清除增量构建成果,让测量结果失真。先在项目根目录分别执行:

./gradlew help --profile
./gradlew assembleStagingDebug --profile

Windows 使用:

gradlew.bat help --profile
gradlew.bat assembleStagingDebug --profile

help 基本不执行编译任务,主要反映 Gradle 的启动和项目配置成本。assembleStagingDebug 可以显示实际构建任务花了多长时间。报告通常生成在:

build/reports/profile/

可以按下面的情况判断:

  • 如果 help 已经很慢,重点检查插件、构建脚本、依赖仓库和配置阶段。
  • 如果 help 很快,但 assembleStagingDebug 很慢,查看报告中的慢任务。
  • 如果命令行构建很快,但 Android Studio 导入后长时间没有响应,问题更可能出在 IDE 索引、文件扫描或插件上。
  • 如果首次构建很慢,第二次明显加快,通常是因为首次需要下载依赖、解压 SDK、生成缓存或建立索引,未必属于异常。

还可以使用 Gradle Build Scan 查看更完整的时间线:

./gradlew assembleStagingDebug --scan

Build Scan 可能会把构建信息上传到外部服务。企业项目使用前,应先确认代码和数据安全策略。不能上传时,使用本地 --profile 即可。

在 Android Studio 中,还可以打开 Build Analyzer,查看 Kotlin、资源处理、Dex、注解处理器等任务的耗时,以及增量构建是否生效。

排查依赖解析和网络问题

先用下面的命令观察依赖解析是否长时间停顿:

./gradlew assembleStagingDebug --info

--debug 会生成大量日志,一般只在 --info 无法定位问题时使用。不要公开包含凭据、私有仓库地址或本机路径的完整日志。

固定动态依赖版本

将:

implementation 'com.facebook.android:facebook-android-sdk:[8,9)'

替换成项目已经验证过的明确版本,例如:

implementation 'com.facebook.android:facebook-android-sdk:<verified-version>'

不能脱离项目兼容性直接指定具体版本。先通过依赖报告确认当前解析结果:

./gradlew app:dependencies --configuration stagingDebugRuntimeClasspath

也可以用下面的命令确认某个库为什么会被引入:

./gradlew app:dependencyInsight \
  --dependency facebook-android-sdk \
  --configuration stagingDebugRuntimeClasspath

动态版本、latest.release 和 SNAPSHOT 依赖都会增加远程元数据检查,还可能让不同时间的构建得到不同的依赖树,建议全部固定版本。

检查仓库声明

仓库越多,当某个依赖不存在或网络请求超时时,Gradle 越可能依次查询多个地址。建议在 settings.gradle 中集中声明仓库,只保留项目确实需要的地址:

pluginManagement {
    repositories {
        google()
        mavenCentral()
        gradlePluginPortal()
    }
}

dependencyResolutionManagement {
    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
    repositories {
        google()
        mavenCentral()

        // 仅在确实使用 com.github.* 的 JitPack 依赖时保留
        maven {
            url = uri("https://jitpack.io")
            content {
                includeGroupByRegex("com\\.github\\..*")
            }
        }
    }
}

如果某个私有仓库或 JitPack 无法访问,增加 IDE 内存也不会改善同步速度。可以暂时通过浏览器或命令行验证仓库连通性,但不要把 --refresh-dependencies 作为日常构建参数,因为它会强制重新检查依赖。

如果所有依赖都已经缓存,可以暂时执行:

./gradlew assembleStagingDebug --offline

离线构建很快、在线构建很慢时,问题基本可以缩小到仓库访问、代理、DNS、证书或动态版本解析。缺少依赖的首次导入不适合使用离线模式。

逐个隔离第三方 Gradle 插件

Gradle 插件会在配置或构建过程中运行,对速度的影响往往比普通 implementation 依赖更直接。建议在独立分支中逐个暂时禁用插件,然后比较 ./gradlew help --profile 的结果:

plugins {
    id 'com.android.application'
    id 'kotlin-android'
    id 'kotlin-kapt'

    // 仅用于诊断,逐个禁用后重新测量
    // id 'com.google.gms.google-services'
    // id 'com.google.firebase.crashlytics'
    // id 'hypersdk.plugin'
}

禁用插件后,项目可能因为缺少生成文件或扩展配置而无法完成构建。不过,help 和 Gradle Sync 的耗时变化仍然可以帮助判断配置阶段的瓶颈。不要一次删除所有插件,否则无法确认具体是哪一个插件造成了问题。

同时检查根项目中的以下内容:

  • buildscript 和插件版本;
  • settings.gradle;
  • 自定义 Gradle 脚本;
  • buildSrc 或 convention plugin;
  • 插件配置是否会执行网络请求、Git 命令或遍历大量文件。

优化 Gradle 配置

可以在项目的 gradle.properties 中使用相对保守的配置:

org.gradle.daemon=true
org.gradle.parallel=true
org.gradle.caching=true

org.gradle.jvmargs=-Xmx4g -Dfile.encoding=UTF-8
kotlin.incremental=true

需要注意:

  • Gradle Daemon 在常规环境中通常已经默认启用,显式声明后不一定有变化。
  • org.gradle.parallel=true 主要适用于包含多个可并行模块的项目,单模块应用的收益可能很小。
  • org.gradle.caching=true 只有在任务支持缓存且输入没有变化时才有效。
  • -Xmx 并不是越大越好。物理内存不足时,过大的堆会导致系统换页,速度反而更慢。
  • Android Studio 的 IDE Heap 和 Gradle JVM Heap 是两个不同的设置。修改 IDE 堆并不会改变 Gradle Daemon 的内存。

确认插件兼容后,可以测试配置缓存:

org.gradle.configuration-cache=true
org.gradle.configuration-cache.problems=warn

然后执行两次:

./gradlew help
./gradlew help

配置缓存的效果要到第二次运行才会体现。如果出现插件不兼容、任务读取未声明状态或构建结果异常,应先关闭配置缓存并解决兼容问题,不要长期用 problems=warn 掩盖错误。

检查 KAPT 和 Kotlin 编译

项目应用了:

id 'kotlin-kapt'

但现有依赖中没有明显的 kapt 声明。如果整个项目确实没有使用注解处理器,可以在验证后移除该插件:

plugins {
    id 'com.android.application'
    id 'kotlin-android'
    // id 'kotlin-kapt'
}

先搜索所有模块中是否存在:

kapt 'group:artifact:version'

还要确认是否有其他依赖插件自动配置了 KAPT。未经检查直接删除,可能导致生成代码缺失。

如果项目使用了注解处理器,可以通过 Build Analyzer 或 Gradle Profile 检查相关任务,例如:

kaptGenerateStubs...
kapt...
compile...Kotlin

如果某个处理器不支持增量处理,即使只修改了少量代码,也可能触发大范围重新生成。某些库同时支持 KSP,可以评估迁移,但必须先确认所用版本和生成代码行为是否兼容。

修正并简化 Android DSL

compileSdk 应放在 android 顶层,而不是 defaultConfig 中。建议整理成下面的结构:

android {
    compileSdk 34
    ndkVersion "23.2.8568313"

    defaultConfig {
        minSdk 24
        targetSdk 34
        versionCode 118
        versionName "12.4"

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
        signingConfig signingConfigs.debug
    }

    flavorDimensions "api"

    productFlavors {
        staging {
            dimension "api"
            buildConfigField "String", "API_BASE_URL", API_BASE_URL
            buildConfigField "String", "API_CHECKSUM_URL", CHECKSUM_URL
        }
        production {
            dimension "api"
            buildConfigField "String", "API_BASE_URL", API_BASE_URL
            buildConfigField "String", "API_CHECKSUM_URL", CHECKSUM_URL
        }
    }

    buildFeatures {
        viewBinding true
    }
}

这项调整主要是为了保证 DSL 正确,减少兼容性方面的歧义,本身不一定能明显改善性能。

项目还声明了:

externalNativeBuild {
    cmake {
        version "3.10.2"
    }
}

如果项目没有 C/C++ 代码,也没有配置 CMakeLists.txt,需要确认是否还需要 CMake、NDK 和相关插件配置。如果确实使用了原生代码,应查看 .cxx 目录中的配置和构建日志。ABI 数量、CMake 配置和大型原生依赖都可能增加导入及构建时间。不要只为了提速就删除原生配置,否则可能影响第三方 SDK 或打包结果。

减少变体和不必要任务

两个 product flavor 与多个 build type 会组合出多个变体。Android Studio 同步时需要建立变体模型,项目越大,这部分的耗时越明显。可以只启用日常开发需要的变体:

android {
    variantFilter { variant ->
        def names = variant.flavors*.name
        if (names.contains("production") && variant.buildType.name == "debug") {
            setIgnore(true)
        }
    }
}

是否使用 variantFilter 以及具体采用哪种 API,取决于项目当前的 Android Gradle Plugin 版本。较新的 AGP 更推荐通过 Android Components API 控制变体。实施前先确认项目使用的 AGP 版本,不要只根据 Android Studio 版本判断。

如果只有 Android Studio 导入慢

如果命令行构建速度正常,但 IDE 一直显示 Indexing、Scanning files 或 Downloading sources,可以重点检查:

  • 项目是否放在机械硬盘、网络盘、同步盘或加密目录中;
  • 项目目录和 Gradle 缓存是否被杀毒软件实时扫描;
  • 大型生成目录、日志、解压文件或 Node.js 目录是否被放进项目;
  • 第三方 Android Studio 插件是否在索引期间大量占用 CPU;
  • Android Studio 与 Gradle 使用的 JDK 是否兼容;
  • 系统是否因为内存不足而频繁换页。

除非组织安全策略允许,否则不要排除项目源码目录或整个 Gradle 缓存的安全扫描。也不要把真正的源码、资源或构建脚本标记为 Excluded。

可以用安全模式,或者暂时禁用非必要的 IDE 插件进行对照。如果只有当前项目很慢,应优先检查项目结构。如果所有项目都慢,再检查 IDE、JDK、磁盘和系统环境。

推荐的排查顺序

  1. 连续执行两次 ./gradlew help --profile,区分首次启动和稳定状态。
  2. 连续执行两次目标变体构建,不要执行 Clean,比较增量构建表现。
  3. 用 --offline 对照在线构建,判断问题是否来自依赖仓库或网络。
  4. 固定 facebook-android-sdk:[8,9) 等所有动态版本。
  5. 收紧仓库声明,检查 JitPack、私有仓库和代理的响应速度。
  6. 在独立分支中逐个禁用 hypersdk.plugin、Crashlytics、Google Services 等插件。
  7. 通过 Build Analyzer 找出最慢的任务,重点检查 KAPT、Kotlin、资源、Dex 和 CMake。
  8. 最后再调整 Gradle 堆、并行执行、构建缓存和配置缓存。

拿到 Profile 或 Build Analyzer 中的具体耗时后,才能判断应该优化依赖下载、插件配置、注解处理、原生构建还是 IDE 索引。就当前配置而言,最该先处理的是动态依赖版本、远程仓库访问和第三方插件,而不是继续增加内存。

备注:内容仅供参考。