如何详细分析Android Kotlin项目构建及排查增量构建耗时异常
Hey there! Let's break down your Android build performance questions with practical, actionable steps.
To dig deep into your build's inner workings, here are several powerful methods to get granular insights:
Use Gradle's built-in profiling tools
- Run your build with the
--profileflag (e.g.,./gradlew assembleDebug --profile). This generates a detailed HTML report inbuild/reports/profile/that breaks down task durations, dependencies, and clear bottlenecks. - For interactive, cloud-powered analysis, use the
--scanflag (requires a free Gradle account). It uploads your build data to Gradle's service, giving you visualizations of task execution, cache hits/misses, and performance trends over multiple builds. - Enable verbose logging with
--infoor--debugflags (e.g.,./gradlew assembleDebug --info). This outputs line-by-line details of what each task is doing—perfect for pinpointing exactly where time is being spent.
- Run your build with the
Leverage Android Studio's Build Analyzer
- Open Android Studio, go to
View > Tool Windows > Build(or click the "Build" tab at the bottom). After a build finishes, click "Analyze Build" to launch the tool. It highlights slow tasks, unused dependencies, and incremental build issues directly in the IDE with actionable fixes.
- Open Android Studio, go to
Profile kapt specifically
- Add
kapt.verbose=trueto your module-levelbuild.gradle.kts(orbuild.gradle) to get detailed logs about annotation processing. This shows which processors are running, how many classes they're handling, and where delays occur.
- Add
Inspect task dependencies and up-to-date status
- Run
./gradlew tasks --allto see all tasks and their dependency chains. - Use
./gradlew <task-name> --up-to-dateto check why a task isn't marked as UP-TO-DATE (critical for incremental build issues). The output will list changed inputs/outputs that triggered the task to rerun.
- Run
Since these tasks are running even when no code changes are made, let's troubleshoot each one systematically:
针对:app:kaptDebugKotlin
Check if your annotation processors support incremental processing
- Not all processors play nice with incremental builds. Look for processors that use the
@IncrementalAnnotationProcessorannotation, or check their documentation for incremental support (e.g., Dagger 2.26+ supports this, but older versions don't). - Enable worker API for kapt by adding
kapt.use.worker.api=trueto your module-levelbuild.gradle.kts—this lets kapt parallelize annotation processing across multiple threads. - Run
./gradlew :app:kaptDebugKotlin --infoand look for lines like "Incremental annotation processing requested but not supported by processor". These are the culprits forcing full rebuilds.
- Not all processors play nice with incremental builds. Look for processors that use the
Verify build cache configuration
- Ensure your
gradle.propertieshasorg.gradle.caching=trueenabled. This lets Gradle reuse outputs from previous builds even if tasks are retriggered. - Check if the kapt task's inputs/outputs are stable. Sometimes processors generate files with dynamic content (like timestamps) that invalidate the cache. Use
./gradlew :app:kaptDebugKotlin --dry-run --infoto list all inputs/outputs and spot any unstable entries.
- Ensure your
Check for unintended file changes
- Even if you didn't modify code, tools like version control, IDE plugins, or system processes might update file timestamps in your
build/orsrc/directories. Runfind . -type f -mtime -1min your project root to see recently modified files—this can reveal hidden changes triggering kapt.
- Even if you didn't modify code, tools like version control, IDE plugins, or system processes might update file timestamps in your
针对:app:processDebugResources
Audit your resource files
- Large numbers of resources (especially vector drawables, XML layouts, or localized strings) can slow down processing. Check for duplicate resources, unused resources (use Android Studio's
Refactor > Remove Unused Resources), or XML files with syntax errors (these force full resource rebuilds). - Use
resConfigsin your module-levelbuild.gradle.ktsto only include the resource locales/densities you need. For example:
This reduces the number of resources processed each time.android { defaultConfig { resConfigs("en", "zh", "xxhdpi") } }
- Large numbers of resources (especially vector drawables, XML layouts, or localized strings) can slow down processing. Check for duplicate resources, unused resources (use Android Studio's
Check incremental resource processing settings
- Enable
android.enableResourceOptimizations=truein yourgradle.properties—this turns on incremental resource processing for Android Gradle Plugin 3.0+. - Run
./gradlew :app:processDebugResources --infoand look for lines indicating "full resource build" instead of "incremental resource build". If it's doing a full build every time, check if any resource files are being modified unexpectedly, or if you have dependencies that generate resources dynamically.
- Enable
Fix cache issues
- Make sure
org.gradle.caching=trueis set, and clear the Gradle cache if needed with./gradlew cleanBuildCache. Sometimes corrupted cache entries cause unnecessary rebuilds.
- Make sure
Bonus: Optimize your gradle.properties
Based on the snippet you provided, here are key additions to boost build performance:
org.gradle.jvmargs=-Xmx4608M -XX:MaxMetaspaceSize=512M -XX:+HeapDumpOnOutOfMemoryError org.gradle.daemon=true org.gradle.parallel=true org.gradle.configureondemand=true org.gradle.caching=true android.enableBuildCache=true android.enableResourceOptimizations=true
内容的提问来源于stack exchange,提问作者Buckstabue

