Tệp bản dựng chỉ định các phần phụ thuộc trực tiếp, nhưng mỗi phần phụ thuộc đó có thể yêu cầu các phần phụ thuộc khác. Các phần phụ thuộc chuyển tiếp này nhanh chóng làm tăng biểu đồ phần phụ thuộc tổng thể, thường là với các phiên bản xung đột.
Khi các phần minor
(tính năng mới) hoặc patch
(sửa lỗi) thay đổi, thư viện vẫn có thể tương thích và ít có khả năng ảnh hưởng đến ứng dụng của bạn.
Ví dụ: giả sử ứng dụng của bạn phụ thuộc vào thư viện A và thư viện B, các thư viện này lại phụ thuộc vào các phiên bản khác nhau của thư viện C.
Trong trường hợp này, theo mặc định, Gradle sẽ chọn phiên bản mới nhất của thư viện C. Điều này có thể gây ra các vấn đề về biên dịch hoặc thời gian chạy. Trong ví dụ này, thư viện C được phân giải thành 2.1.1, nhưng lưu ý rằng thư viện A đã yêu cầu thư viện C 1.0.3. Phần chính của số phiên bản đã thay đổi, cho thấy có các thay đổi không tương thích, chẳng hạn như các hàm hoặc loại đã bị xoá. Điều này có thể khiến các lệnh gọi được thực hiện từ thư viện A gặp sự cố.
Ứng dụng của bạn có thể có các phần phụ thuộc trực tiếp cũng là phần phụ thuộc bắc cầu.
Trong trường hợp như vậy, các phần phụ thuộc bắc cầu mới hơn có thể ghi đè phiên bản mà bạn yêu cầu trực tiếp trong ứng dụng.
Gradle xem xét tất cả phiên bản đề xuất cho tất cả phần phụ thuộc trong biểu đồ để xác định phiên bản mới nhất của mỗi phần phụ thuộc. Bạn có thể dùng các tác vụ Gradle cơ bản và các công cụ nâng cao khác để xác định phiên bản của mỗi phần phụ thuộc mà Gradle đã phân giải. Việc so sánh các thay đổi trong độ phân giải này là yếu tố then chốt để hiểu rõ và giảm thiểu rủi ro của quá trình nâng cấp.
Ví dụ: bạn có thể sử dụng tác vụ dependencies
của Gradle bằng cách chạy ./gradlew
app:dependencies
để hiển thị cây gồm tất cả các phần phụ thuộc mà mô-đun ứng dụng sử dụng. Khi chạy công cụ này trên một ứng dụng sử dụng các thư viện như trong hình 2, chúng ta sẽ thấy
1: releaseRuntimeClasspath - Runtime classpath of /release.
2: +--- org.jetbrains.kotlin:kotlin-stdlib:2.0.0
3: | +--- ... (omitted for brevity) ...
4: +--- com.sample:library.a:1.2.3
5: | +--- com.sample:library.c:2.1.1
6: | | \--- org.jetbrains.kotlin:kotlin-stdlib:2.0.0 (*)
7: | \--- org.jetbrains.kotlin:kotlin-stdlib:2.0.0 (*)
8: +--- com.sample:library.c:1.4.1 -> 2.1.1 (*)
Phần này của báo cáo cho thấy một số phần phụ thuộc đã được phân giải cho cấu hình releaseRuntimeClasspath
.
Bất cứ khi nào bạn thấy ->
trong báo cáo về phần phụ thuộc, một trình yêu cầu (ứng dụng hoặc thư viện khác của bạn) sẽ sử dụng một phiên bản của phần phụ thuộc đó mà ứng dụng không mong đợi. Trong nhiều trường hợp, điều này không gây ra vấn đề nào vì hầu hết các thư viện đều được viết để có khả năng tương thích ngược. Tuy nhiên, một số thư viện có thể thực hiện các thay đổi không tương thích và báo cáo này có thể giúp bạn xác định nguồn gốc của các vấn đề mới liên quan đến hành vi của ứng dụng.
Bạn có thể xem thêm thông tin chi tiết về cách sử dụng tính năng báo cáo phần phụ thuộc của Gradle tại phần Xem và gỡ lỗi phần phụ thuộc.
Bạn có thể chỉ định trực tiếp các phiên bản được yêu cầu trong danh mục phiên bản hoặc trong Bảng kê khai thành phần (BOM).
Giải pháp trực tiếp về thông số kỹ thuật của phiên bản
Các phiên bản phần phụ thuộc mà bạn chỉ định sẽ trở thành đề xuất phân giải phiên bản.
Ví dụ: để yêu cầu phiên bản 1.7.3 của thư viện androidx.compose.ui:ui
làm phần phụ thuộc trong app/build.gradle.kts
:
dependencies {
implementation("androidx.compose.ui:ui:1.7.3")
}
Phiên bản 1.7.3 trở thành phiên bản đề xuất. Gradle phân giải thành phiên bản mới nhất trong số 1.7.3 và các phiên bản khác của cùng một thư viện do các phần phụ thuộc bắc cầu yêu cầu.
Độ phân giải của danh mục phiên bản
Danh mục phiên bản xác định các biến để theo dõi phiên bản của các phần phụ thuộc được dùng trong toàn bộ ứng dụng. Nếu bạn dùng một biến trong danh mục phiên bản, thì các phần phụ thuộc đã chỉ định của biến đó sẽ được thêm vào các đề xuất để phân giải phiên bản. Các biến không sử dụng trong danh mục phiên bản sẽ bị bỏ qua.
Ví dụ: để chỉ định phiên bản 1.7.3 của androidx.compose.ui:ui
là phần phụ thuộc trong tệp gradle/libs.versions.toml
:
[versions]
ui = "1.7.3"
[libraries]
androidx-compose-ui = { group = "androidx.compose.ui", name = "ui", version.ref = "ui" }
Thao tác này xác định một biến có tên libs.androidx.compose.ui
để đại diện cho thư viện. Phiên bản này không được coi là đề xuất trừ phi bạn sử dụng biến đó để chỉ định một phần phụ thuộc.
Cách yêu cầu thư viện và phiên bản của thư viện đó trong app/build.gradle.kts
:
dependencies {
implementation(libs.androidx.compose.ui)
}
Gradle giải quyết theo cách tương tự như đối với quy cách trực tiếp.
Nghị quyết Bảng kê khai thành phần (BOM)
Các phiên bản cho tất cả thư viện xuất hiện trong BOM sẽ trở thành ứng cử viên cho việc phân giải phiên bản. Xin lưu ý rằng thư viện chỉ được dùng làm phần phụ thuộc nếu được chỉ định là trực tiếp hoặc gián tiếp. Các thư viện khác trong BOM sẽ bị bỏ qua.
Các phiên bản BOM ảnh hưởng đến các phần phụ thuộc trực tiếp cũng như tất cả các phần phụ thuộc bắc cầu xuất hiện trong BOM.
Ví dụ: chỉ định BOM làm phần phụ thuộc nền tảng trong app/build.gradle.kts
:
dependencies {
implementation(platform("androidx.compose:compose-bom:2024.10.00"))
implementation("androidx.compose.ui:ui")
}
Mọi thư viện mà bạn muốn sử dụng làm phần phụ thuộc đều không yêu cầu thông số kỹ thuật phiên bản; phiên bản được yêu cầu đến từ BOM.
Xin lưu ý rằng bạn cũng có thể dùng danh mục phiên bản để tạo các biến cho Bảng kê khai thành phần (BOM) và thư viện. Bỏ qua số phiên bản trong danh mục phiên bản của các thư viện xuất hiện trong phần phụ thuộc BOM.
Ví dụ: danh mục phiên bản của bạn chứa BOM và số phiên bản của BOM, nhưng không chỉ định phiên bản cho các thư viện mà bạn tham chiếu từ BOM:
[versions]
composeBom = "2024.10.00"
[libraries]
androidx-compose-bom = { group = "androidx.compose", name = "compose-bom", version.ref = "composeBom" }
androidx-compose-ui = { group = "androidx.compose.ui", name = "ui" }
app/build.gradle.kts
tham chiếu đến Bảng kê khai thành phần (BOM) và các thư viện bằng cách sử dụng các biến được xác định trong danh mục phiên bản:
dependencies {
implementation(platform(libs.androidx.compose.bom))
implementation(libs.androidx.compose.ui)
}
Phiên bản của thư viện đó được chỉ định trong BOM sẽ trở thành ứng cử viên cho độ phân giải của Gradle. Ngoài ra, tất cả các phiên bản thư viện khác được chỉ định trong BOM sẽ trở thành phiên bản đề xuất, cho dù bạn có trực tiếp sử dụng các phiên bản đó làm phần phụ thuộc hay không.
Ví dụ: Giả sử BOM chỉ định các phiên bản cho thư viện A, B và C. Ứng dụng của bạn muốn trực tiếp sử dụng thư viện A làm phần phụ thuộc, cũng như thư viện D. Thư viện D sử dụng thư viện B làm phần phụ thuộc. Không có ứng dụng nào sử dụng thư viện C.
Các thư viện A, B và D là các phần phụ thuộc trong ứng dụng; thư viện C bị bỏ qua. Gradle sử dụng các phiên bản A và B được chỉ định trong BOM làm ứng cử viên, mặc dù bạn không trực tiếp chỉ định thư viện B làm phần phụ thuộc.
Nếu thư viện D yêu cầu phiên bản thư viện B thấp hơn 2.0.1, Gradle sẽ phân giải thành 2.0.1. Nếu thư viện D yêu cầu phiên bản thư viện B cao hơn, Gradle sẽ phân giải thành phiên bản đó.