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

Dependencies

Dependencies là các thư viện bên ngoài mà ứng dụng của bạn sử dụng. Gradle giúp quản lý việc tải, cập nhật và tích hợp các thư viện này một cách tự động.

Khi phát triển Android app, bạn sử dụng nhiều thư viện:

  • AndroidX libraries - Core Android components
  • Jetpack Compose - UI framework
  • Retrofit - Networking
  • Room - Database
  • Hilt/Koin - Dependency Injection

Gradle tự động:

  1. Tải thư viện từ repositories (Maven Central, Google)
  2. Tải các transitive dependencies (dependencies của dependency)
  3. Resolve conflicts giữa các versions

Configuration xác định khi nàonhư thế nào dependency được sử dụng:

dependencies {
implementation(libs.retrofit) // Compile + Runtime
api(libs.retrofit) // Compile + Runtime (exported)
compileOnly(libs.lombok) // Compile only
runtimeOnly(libs.jdbc.driver) // Runtime only
testImplementation(libs.junit) // Unit tests
androidTestImplementation(libs.espresso)// Instrumented tests
ksp(libs.room.compiler) // Annotation processing
debugImplementation(libs.leakcanary) // Debug build only
}
Configuration Compile Classpath Runtime Classpath Exported Use Case
implementation Thư viện internal
api Thư viện cần expose
compileOnly Compile-time only
runtimeOnly Runtime plugins
testImplementation ✅ (tests) ✅ (tests) Unit tests
androidTestImplementation ✅ (Android tests) ✅ (Android tests) Instrumented tests

flowchart LR
subgraph "implementation"
A1[":app"] --> B1[":feature"]
B1 --> C1["Retrofit"]
A1 -.->|"❌ Cannot access"| C1
end
subgraph "api"
A2[":app"] --> B2[":core:network"]
B2 --> C2["Retrofit"]
A2 -->|"✅ Can access"| C2
end
style C1 fill:#ffcdd2
style C2 fill:#c8e6c9

Dependency chỉ visible trong module hiện tại:

home/build.gradle.kts
dependencies {
implementation(libs.retrofit) // Retrofit chỉ visible trong :feature:home
}
:app → :feature:home → Retrofit
❌ Không thể access Retrofit từ :app

Ưu điểm:

  • Build nhanh hơn (incremental)
  • Khi libs.retrofit thay đổi, chỉ rebuild :feature:home
  • Encapsulation tốt hơn

Dependency được export cho modules phụ thuộc:

network/build.gradle.kts
dependencies {
api(libs.retrofit) // Retrofit visible cho tất cả modules dùng :core:network
}
:app → :core:network → Retrofit
✅ :app có thể access Retrofit

Khi nào dùng api:

  • Khi public interface của module expose types từ dependency
  • Ví dụ: fun createRetrofitService(): Retrofit

⚠️ Quan trọng: Ưu tiên dùng implementation trừ khi cần expose types. Quá nhiều api làm chậm build.


Các thư viện code generation sử dụng annotation processors:

plugins {
alias(libs.plugins.ksp)
}
dependencies {
implementation(libs.room.runtime)
implementation(libs.room.ktx)
ksp(libs.room.compiler) // KSP processor
implementation(libs.hilt.android)
ksp(libs.hilt.compiler)
}
plugins {
id("org.jetbrains.kotlin.kapt")
}
dependencies {
implementation(libs.hilt.android)
kapt(libs.hilt.compiler) // KAPT processor
}
KSP KAPT
Tốc độ ⚡ Nhanh (2x) 🐢 Chậm
Kotlin-native ✅ Có ❌ Wraps javac
Recommended ✅ Có ⚠️ Chỉ khi thư viện chưa hỗ trợ KSP

💡 Mẹo: Xem Migrate from KAPT to KSP để chuyển đổi.


Thêm dependencies cho build variant cụ thể:

dependencies {
// Debug only
debugImplementation(libs.leakcanary)
debugImplementation(libs.compose.ui.tooling)
// Release only
releaseImplementation(libs.firebase.crashlytics)
// Flavor specific
demoImplementation(libs.demo.mode.library)
fullImplementation(libs.premium.features)
// Variant specific (flavor + build type)
devDebugImplementation(libs.mock.server)
}

Thêm dependency vào module khác trong cùng project:

app/build.gradle.kts
dependencies {
implementation(project(":core:network"))
implementation(project(":core:database"))
implementation(project(":feature:home"))
implementation(project(":feature:profile"))
}
// :feature:home/build.gradle.kts
dependencies {
implementation(project(":core:network"))
implementation(project(":core:common"))
}

Bill of Materials (BOM) quản lý versions của một họ thư viện:

dependencies {
// Import Compose BOM
implementation(platform(libs.androidx.compose.bom))
// Compose libraries - KHÔNG cần version
implementation(libs.androidx.ui)
implementation(libs.androidx.ui.graphics)
implementation(libs.androidx.material3)
// Import Firebase BOM
implementation(platform(libs.firebase.bom))
// Firebase libraries - KHÔNG cần version
implementation(libs.firebase.analytics)
implementation(libs.firebase.crashlytics)
}

📝 Lưu ý: BOM đảm bảo các thư viện trong cùng một họ có versions compatible với nhau.


libs.versions.toml
[versions]
compose-bom = "2024.11.00"
activity-compose = "1.9.3"
[libraries]
androidx-compose-bom = { group = "androidx.compose", name = "compose-bom", version.ref = "compose-bom" }
androidx-ui = { group = "androidx.compose.ui", name = "ui" }
androidx-ui-graphics = { group = "androidx.compose.ui", name = "ui-graphics" }
androidx-ui-tooling = { group = "androidx.compose.ui", name = "ui-tooling" }
androidx-ui-tooling-preview = { group = "androidx.compose.ui", name = "ui-tooling-preview" }
androidx-material3 = { group = "androidx.compose.material3", name = "material3" }
androidx-activity-compose = { group = "androidx.activity", name = "activity-compose", version.ref = "activity-compose" }
dependencies {
implementation(platform(libs.androidx.compose.bom))
implementation(libs.androidx.ui)
implementation(libs.androidx.ui.graphics)
implementation(libs.androidx.material3)
implementation(libs.androidx.activity.compose)
debugImplementation(libs.androidx.ui.tooling)
debugImplementation(libs.androidx.ui.tooling.preview)
}
[versions]
room = "2.6.1"
[libraries]
room-runtime = { group = "androidx.room", name = "room-runtime", version.ref = "room" }
room-ktx = { group = "androidx.room", name = "room-ktx", version.ref = "room" }
room-compiler = { group = "androidx.room", name = "room-compiler", version.ref = "room" }
[plugins]
room = { id = "androidx.room", version.ref = "room" }
plugins {
alias(libs.plugins.room)
alias(libs.plugins.ksp)
}
room {
schemaDirectory("$projectDir/schemas")
}
dependencies {
implementation(libs.room.runtime)
implementation(libs.room.ktx)
ksp(libs.room.compiler)
}
[versions]
retrofit = "2.11.0"
okhttp = "4.12.0"
[libraries]
retrofit = { module = "com.squareup.retrofit2:retrofit", version.ref = "retrofit" }
retrofit-gson = { module = "com.squareup.retrofit2:converter-gson", version.ref = "retrofit" }
retrofit-kotlinx-serialization = { module = "com.squareup.retrofit2:converter-kotlinx-serialization", version.ref = "retrofit" }
okhttp-logging = { module = "com.squareup.okhttp3:logging-interceptor", version.ref = "okhttp" }
[bundles]
retrofit = ["retrofit", "retrofit-gson", "okhttp-logging"]
dependencies {
implementation(libs.bundles.retrofit)
// hoặc
implementation(libs.retrofit)
implementation(libs.retrofit.gson)
implementation(libs.okhttp.logging)
}
[versions]
hilt = "2.52"
hilt-navigation-compose = "1.2.0"
[libraries]
hilt-android = { group = "com.google.dagger", name = "hilt-android", version.ref = "hilt" }
hilt-compiler = { group = "com.google.dagger", name = "hilt-compiler", version.ref = "hilt" }
hilt-navigation-compose = { group = "androidx.hilt", name = "hilt-navigation-compose", version.ref = "hilt-navigation-compose" }
[plugins]
hilt = { id = "com.google.dagger.hilt.android", version.ref = "hilt" }
plugins {
alias(libs.plugins.hilt)
alias(libs.plugins.ksp)
}
dependencies {
implementation(libs.hilt.android)
implementation(libs.hilt.navigation.compose)
ksp(libs.hilt.compiler)
}
[versions]
navigation = "2.8.4"
kotlinx-serialization = "1.7.3"
[libraries]
navigation-compose = { group = "androidx.navigation", name = "navigation-compose", version.ref = "navigation" }
kotlinx-serialization-json = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref = "kotlinx-serialization" }
[plugins]
kotlin-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" }
plugins {
alias(libs.plugins.kotlin.serialization)
}
dependencies {
implementation(libs.navigation.compose)
implementation(libs.kotlinx.serialization.json)
}
[versions]
coil = "2.7.0"
[libraries]
coil-compose = { module = "io.coil-kt:coil-compose", version.ref = "coil" }
coil-gif = { module = "io.coil-kt:coil-gif", version.ref = "coil" }
coil-svg = { module = "io.coil-kt:coil-svg", version.ref = "coil" }
dependencies {
implementation(libs.coil.compose)
}

Terminal window
# Xem tất cả dependencies của module :app
./gradlew :app:dependencies
# Xem configuration cụ thể
./gradlew :app:dependencies --configuration releaseRuntimeClasspath
# Tìm dependency cụ thể
./gradlew :app:dependencyInsight --dependency retrofit

Sử dụng Gradle Versions Plugin để kiểm tra updates:

settings.gradle.kts
plugins {
id("com.github.ben-manes.versions") version "0.51.0"
}
Terminal window
./gradlew dependencyUpdates

// ✅ Tốt
implementation(libs.retrofit)
// ❌ Tránh
implementation("com.squareup.retrofit2:retrofit:2.11.0")
// ✅ Mặc định dùng implementation
implementation(libs.retrofit)
// ⚠️ Chỉ dùng api khi cần export types
api(libs.retrofit)
// ✅ Khuyến nghị
ksp(libs.room.compiler)
// ⚠️ Legacy - chỉ khi thư viện chưa hỗ trợ KSP
kapt(libs.room.compiler)
// ❌ Nguy hiểm - có thể break build bất ngờ
implementation("com.example:library:1.+")
implementation("com.example:library:latest.release")
// ✅ Explicit version
implementation("com.example:library:1.2.3")
// ✅ BOM quản lý compatible versions
implementation(platform(libs.androidx.compose.bom))
implementation(libs.androidx.ui)
implementation(libs.androidx.material3)

Concept Mô tả
implementation Dependency internal, không export
api Dependency được export cho dependent modules
compileOnly Chỉ compile-time
runtimeOnly Chỉ runtime
ksp Kotlin Symbol Processing (annotation processor)
testImplementation Dependencies cho unit tests
debugImplementation Dependencies cho debug builds
platform() Import BOM để quản lý versions
project() Depend vào module khác trong project