Bỏ qua để đến nội dung

Tối ưu Build

Build chậm là một trong những vấn đề phổ biến nhất khi phát triển Android. Bài viết này hướng dẫn các kỹ thuật để giảm thời gian build và cải thiện năng suất làm việc.

flowchart TB
subgraph "🔍 Phân tích"
A1["Build Scan"]
A2["Profile Build"]
A3["Build Analyzer"]
end
subgraph "⚙️ Cấu hình"
B1["gradle.properties"]
B2["Daemon"]
B3["Parallel Build"]
end
subgraph "📦 Caching"
C1["Build Cache"]
C2["Configuration Cache"]
C3["Incremental Build"]
end
subgraph "🏗️ Module"
D1["Modularization"]
D2["Avoid Unused Dependencies"]
end
A1 --> B1
A2 --> B2
B1 --> C1
B3 --> D1
style A1 fill:#e3f2fd
style B1 fill:#e8f5e9
style C1 fill:#fff3e0
style D1 fill:#fce4ec

Trước khi tối ưu, cần hiểu build đang chậm ở đâu.

Terminal window
# Tạo build scan
./gradlew assembleDebug --scan
# Sau khi build xong, Gradle sẽ hiển thị URL để xem report
Terminal window
# Profile với báo cáo HTML
./gradlew assembleDebug --profile
# Report được tạo tại:
# build/reports/profile/profile-<timestamp>.html
  1. Build app: Build → Make Project
  2. Mở Build → Build Analyzer
  3. Xem chi tiết các tasks chậm

gradle.properties
# Tăng heap size cho Gradle daemon
org.gradle.jvmargs=-Xmx4096m -XX:+HeapDumpOnOutOfMemoryError
# File encoding
-Dfile.encoding=UTF-8
# Tránh GC pauses dài
-XX:+UseParallelGC

Khuyến nghị heap size:

  • Dự án nhỏ: 2GB (-Xmx2048m)
  • Dự án trung bình: 4GB (-Xmx4096m)
  • Dự án lớn: 8GB (-Xmx8192m)

Cảnh báo: Không set heap size quá cao nếu máy không đủ RAM. Để lại ít nhất 2GB cho hệ thống.

# Build các modules song song
org.gradle.parallel=true
# Số worker threads (mặc định = số CPU cores)
org.gradle.workers.max=4
# Bật build cache (cache task outputs)
org.gradle.caching=true
# Configuration cache (cache configuration phase)
org.gradle.configuration-cache=true
# Chỉ configure modules cần thiết
org.gradle.configureondemand=true

Ví dụ gradle.properties tối ưu hoàn chỉnh

Phần tiêu đề “Ví dụ gradle.properties tối ưu hoàn chỉnh”
# gradle.properties - Optimized for build performance
# === JVM Settings ===
org.gradle.jvmargs=-Xmx4096m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 -XX:+UseParallelGC
# === Gradle Daemon ===
org.gradle.daemon=true
# === Parallel & Caching ===
org.gradle.parallel=true
org.gradle.caching=true
org.gradle.configuration-cache=true
org.gradle.configureondemand=true
# === Android Specific ===
android.useAndroidX=true
android.nonTransitiveRClass=true
android.enableJetifier=false
# === Kotlin ===
kotlin.code.style=official
kotlin.incremental=true

// ❌ Dynamic version - slow & unpredictable
implementation("com.example:library:1.+")
implementation("com.example:library:latest.release")
// ✅ Fixed version - fast & predictable
implementation("com.example:library:1.2.3")
// ✅ implementation: Chỉ rebuild module hiện tại khi thay đổi
implementation(libs.retrofit)
// ⚠️ api: Rebuild tất cả dependent modules
api(libs.retrofit)

Kiểm tra dependencies không sử dụng với Dependency Analysis Plugin:

settings.gradle.kts
plugins {
id("com.autonomousapps.dependency-analysis") version "1.32.0"
}
Terminal window
./gradlew buildHealth
// ✅ BOM đảm bảo versions compatible, tránh conflict resolution
implementation(platform(libs.androidx.compose.bom))
implementation(libs.androidx.ui)
implementation(libs.androidx.material3)

KSP nhanh hơn KAPT khoảng 2x:

// ❌ KAPT - chậm
plugins {
id("org.jetbrains.kotlin.kapt")
}
dependencies {
kapt(libs.room.compiler)
}
// ✅ KSP - nhanh
plugins {
alias(libs.plugins.ksp)
}
dependencies {
ksp(libs.room.compiler)
}
Library KSP Support
Room ✅ Có
Hilt ✅ Có
Moshi ✅ Có
Glide ✅ Có (glide-ksp)
Coil Không cần

android {
buildFeatures {
buildConfig = false // Disable nếu không dùng BuildConfig
}
}
android {
buildFeatures {
aidl = false
renderScript = false
resValues = false
shaders = false
}
}
gradle.properties
android.nonTransitiveRClass=true

Điều này ngăn R class chứa resources từ dependencies, giảm compile time.


android {
buildTypes {
debug {
isMinifyEnabled = false // Đã mặc định
isShrinkResources = false
}
}
}

Với Android Gradle Plugin 8.0+, pre-dexing được bật mặc định.

android {
defaultConfig {
// Chỉ build cho emulator khi debug
ndk {
abiFilters += listOf("x86_64", "arm64-v8a")
}
}
}

Hoặc sử dụng split APKs:

android {
splits {
abi {
isEnable = true
reset()
include("x86_64", "arm64-v8a")
isUniversalApk = false
}
}
}

Chia project thành các modules nhỏ giúp incremental build hiệu quả hơn:

app/ # App module
├── feature/
│ ├── home/ # Feature module
│ ├── profile/
│ └── settings/
├── core/
│ ├── network/ # Core module
│ ├── database/
│ └── common/
└── data/
└── repository/ # Data module
// ❌ Quá nhiều api làm chậm build
dependencies {
api(libs.retrofit)
api(libs.gson)
api(libs.okhttp)
}
// ✅ Chỉ api những gì cần expose
dependencies {
implementation(libs.retrofit)
implementation(libs.gson)
api(libs.okhttp.core) // Chỉ expose OkHttp nếu cần
}

# GitHub Actions example
- name: Cache Gradle
uses: actions/cache@v4
with:
path: |
~/.gradle/caches
~/.gradle/wrapper
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
restore-keys: |
${{ runner.os }}-gradle-
Terminal window
./gradlew assembleRelease --parallel --max-workers=4
Terminal window
# Skip tests khi build release
./gradlew assembleRelease -x test -x lint
# Disable daemon trên CI (mỗi build là fresh)
org.gradle.daemon=false

Gradle Build Scan cung cấp insights chi tiết:

Terminal window
./gradlew build --scan

Sau đó truy cập URL được cung cấp để xem:

  • Task execution timeline
  • Dependency resolution
  • Cache hits/misses
  • Build warnings
build.gradle.kts
gradle.taskGraph.afterTask { task ->
if (task.state.didWork) {
println("${task.path} took ${(task.state.endTime - task.state.startTime)}ms")
}
}

  • Tăng Gradle heap size phù hợp
  • Bật parallel execution
  • Bật build caching
  • Bật configuration cache
  • Sử dụng fixed versions (không dùng + hoặc latest)
  • Ưu tiên implementation thay api
  • Loại bỏ dependencies không dùng
  • Sử dụng BOM cho thư viện families
  • Migrate từ KAPT sang KSP
  • Sử dụng incremental annotation processing
  • Disable features không dùng (aidl, renderScript, etc.)
  • Bật non-transitive R classes
  • Modularize project hợp lý
  • Tránh circular dependencies