Sự phụ thuộc lẫn nhau giữa công cụ và thư viện

Phần phụ thuộc bản dựng là các thành phần bên ngoài cần thiết để tạo thành công dự án. Một bản dựng có thể phụ thuộc vào thư viện, trình bổ trợ, dự án phụ, SDK Android, bộ công cụ như trình biên dịch KotlinJava, các môi trường phát triển như Android Studio và chính Gradle.

Mỗi phần phụ thuộc có thể yêu cầu các phần phụ thuộc khác. Chúng tôi gọi đây là phần phụ thuộc bắc cầu và có thể nhanh chóng tăng số lượng phần phụ thuộc tổng thể mà ứng dụng của bạn sử dụng. Khi bạn muốn nâng cấp một phần phụ thuộc, cho dù đó là thư viện, công cụ hay SDK Android, quá trình nâng cấp đó có thể tạo hiệu ứng lan truyền, nâng cấp nhiều phần phụ thuộc khác.

Thông thường, việc này sẽ không gây ra khó khăn gì vì nhiều thư viện tuân theo một lược đồ được gọi là Phiên bản ngữ nghĩa. Các thư viện này hạn chế các loại thay đổi mà chúng thực hiện để cung cấp khả năng tương thích với các phiên bản thấp hơn.

Việc tạo phiên bản ngữ nghĩa tuân theo định dạng major.minor.patch. Ví dụ: trong số phiên bản 4.8.3, 4 là phiên bản major, 8 là phiên bản minor và 3 là số patch. Khi phần major thay đổi, thư viện có thể có các thay đổi có thể gây lỗi trong API hoặc hành vi. Điều này có thể ảnh hưởng đến bản dựng hoặc hành vi của ứng dụng.

Khi các phần minor (tính năng mới) hoặc patch (sửa lỗi) thay đổi, nhà phát triển thư viện sẽ cho bạn biết rằng thư viện vẫn tương thích và không ảnh hưởng đến ứng dụng của bạn.

Bạn cần theo dõi những thay đổi như vậy và một số Công cụ nâng cấp phần phụ thuộc có thể hỗ trợ bạn.

Mối quan hệ trong bản dựng

Bản dựng Android chứa các mối quan hệ giữa:

  • Mã nguồn – mã và tài nguyên mà bạn có quyền kiểm soát
  • Phần phụ thuộc thư viện – các thư viện hoặc mô-đun bên ngoài mà dự án và dự án phụ của bạn bao gồm khi tạo
  • Công cụ – trình biên dịch, trình bổ trợ và SDK dịch nguồn của bạn thành một ứng dụng hoặc thư viện
Xây dựng các phần phụ thuộc và mối quan hệ giữa các phần phụ thuộc đó
Hình 1. Xây dựng mối quan hệ

Mã nguồn

Mã nguồn là mã Kotlin hoặc Java mà bạn viết trong ứng dụng hoặc thư viện. (Để biết thông tin chi tiết về cách sử dụng C++, hãy xem Android NDK.)

Mã nguồn phụ thuộc vào các thư viện (bao gồm cả thư viện thời gian chạy Kotlin và Java) và SDK Android, đồng thời yêu cầu trình biên dịch Kotlin hoặc Java tương ứng.

Một số mã nguồn có các chú thích cần xử lý thêm. Ví dụ: nếu đang viết mã Jetpack Compose, bạn sẽ thêm các chú giải như @Composable cần được trình bổ trợ trình biên dịch Kotlin của Compose xử lý. Các chú giải khác có thể được xử lý bằng Trình xử lý ký hiệu Kotlin (KSP) hoặc các công cụ xử lý chú giải riêng biệt.

Phần phụ thuộc thư viện

Thư viện chứa mã byte được đưa vào như một phần của ứng dụng. Đây có thể là tệp JAR Java, thư viện Android (AAR) hoặc một dự án phụ trong bản dựng. Nhiều thư viện tuân theo tiêu chuẩn Phiên bản ngữ nghĩa. Phương pháp này có thể giúp bạn biết khi nào các thư viện này vẫn tương thích (hoặc không tương thích) khi được nâng cấp.

Các thư viện có thể phụ thuộc vào các thư viện khác để tái sử dụng, gọi là phần phụ thuộc bắc cầu. Điều này giúp giảm các phần phụ thuộc mà bạn phải quản lý một cách rõ ràng; bạn chỉ định các phần phụ thuộc mà bạn trực tiếp sử dụng và Gradle sẽ đưa các phần phụ thuộc đó vào cùng với các phần phụ thuộc bắc cầu đó. Xin lưu ý rằng khi bạn nâng cấp các phần phụ thuộc trực tiếp, các phần phụ thuộc bắc cầu đó có thể được nâng cấp.

Đôi khi, một thư viện có thể yêu cầu các phiên bản tối thiểu của SDK Android trong thời gian chạy (minSdk) hoặc thời gian biên dịch (compileSdk). Điều này là cần thiết khi một thư viện sử dụng các hàm có trong SDK Android hoặc các API JDK được cung cấp. minSdk hiệu quả của ứng dụng là minSdk cao nhất mà ứng dụng yêu cầu và tất cả các phần phụ thuộc thư viện trực tiếp và bắc cầu của ứng dụng.

Khi sử dụng một số thư viện, bạn có thể phải dùng một trình bổ trợ Gradle cụ thể. Các trình bổ trợ trợ giúp này thường cài đặt Trình xử lý biểu tượng Kotlin hoặc các trình xử lý chú giải khác tạo mã hoặc sửa đổi quá trình biên dịch nguồn để hỗ trợ bạn sử dụng các tính năng của thư viện. Ví dụ: Jetpack Room bao gồm các chú giải và KSP giúp chuyển đổi các chú giải đó thành mã được tạo để truy xuất và sửa đổi dữ liệu trong cơ sở dữ liệu. Jetpack Compose yêu cầu trình bổ trợ biên dịch Compose sửa đổi các hàm được chú thích để quản lý cách thức và thời điểm chạy lại hàm đó.

Công cụ

Gradle

Gradle là công cụ bản dựng đọc các tệp bản dựng và tạo ứng dụng hoặc thư viện, đồng thời hiển thị một API cho các trình bổ trợ để mở rộng chức năng của trình bổ trợ. Gradle chạy nhiều quy trình trên một hoặc nhiều máy ảo Java và các trình bổ trợ Java của Gradle gọi công cụ Java bên trong JDK.

Trình bổ trợ Gradle

Trình bổ trợ Gradle mở rộng Gradle bằng cách xác định các tác vụ và cấu hình mới. Việc áp dụng trình bổ trợ cho bản dựng sẽ bật các chức năng bản dựng cụ thể, được định cấu hình dưới dạng dữ liệu trong tập lệnh bản dựng. Đối với các bản dựng Android, trình bổ trợ Gradle quan trọng nhất là Trình bổ trợ Android cho Gradle (AGP).

Trình biên dịch

Trình biên dịch Kotlin hoặc Java biến đổi mã nguồn thành mã byte có thể thực thi. Trình biên dịch Kotlin hiển thị một API trình bổ trợ cho phép chạy mã phân tích và tạo mã bên ngoài ngay bên trong trình biên dịch, truy cập vào cấu trúc mã được phân tích cú pháp.

Trình bổ trợ trình biên dịch

Trình bổ trợ trình biên dịch thực hiện việc phân tích và tạo mã bên trong trình biên dịch Kotlin trong khi trình biên dịch Kotlin đang phân tích mã của bạn và được cài đặt khi bạn áp dụng trình bổ trợ Gradle cho bản dựng.

SDK Android

SDK Android chứa Nền tảng Android và API Java cho một phiên bản Android cụ thể, cũng như các công cụ tương ứng. Những công cụ này giúp bạn quản lý SDK, xây dựng ứng dụng cũng như giao tiếp với và mô phỏng các thiết bị Android.

Mỗi phiên bản SDK Android đều cung cấp các API Java cụ thể mà mã nguồn của bạn có thể truy cập, đồng thời hỗ trợ đơn giản hoá để sử dụng các API đó trên các phiên bản Android cũ hơn.

JDK

Bộ phát triển Java, chứa các thư viện Java và tệp thực thi để biên dịch nguồn Java và chạy các ứng dụng Java. Có một số JDK đang hoạt động trong một bản dựng Android. Hãy xem bài viết Phiên bản Java trong bản dựng Android để biết thêm thông tin chi tiết.

Phạm vi Gradle

Gradle nhóm các phần phụ thuộc của thư viện thành nhiều phạm vi (được gọi là cấu hình trong API Gradle), cho phép bạn chỉ định các nhóm phần phụ thuộc của thư viện khác nhau để dùng trong các phần khác nhau của bản dựng. Ví dụ: có thể bạn không muốn đưa các thư viện kiểm thử như JUnit vào ứng dụng hoặc thư viện đã phát hành, nhưng bạn muốn có các thư viện đó khi tạo và thực thi kiểm thử đơn vị. Bạn cũng sử dụng phạm vi để thêm trình xử lý chú thích hoặc biểu tượng nhằm phân tích mã.

Ví dụ: AGP xác định phạm vi implementationapi, cách bạn chỉ định liệu một phần phụ thuộc có được hiển thị cho người dùng dự án phụ hay không. Hãy xem phần Định cấu hình phần phụ thuộc để biết nội dung mô tả về các phạm vi này và các phạm vi khác được sử dụng trong bản dựng Android.

Thêm phần phụ thuộc thư viện trong khối dependencies của tệp bản dựng, dưới dạng chuỗi group:artifact:version:

Kotlin

// In a module-level build script
// explicit dependency strings ("group:artifact:version")
dependencies {
    implementation("com.example:library1:1.2.3")
    api("com.example:library2:1.1.1")
}

Groovy

// In a module-level build script
// explicit dependency strings ("group:artifact:version")
dependencies {
    implementation 'com.example:library1:1.2.3'
    api 'com.example:library2:1.1.1'
}

hoặc trong Danh mục phiên bản:

# Version catalog - gradle/libs.versions.toml
[versions]
exampleLib = "1.2.3"
examplePlugin = "2.3.4"

[libraries]
example-library = { group = "com.example", name = "library", version.ref = "exampleLib" }

[plugins]
example-plugin = { id = "com.example.plugin", version.ref = "examplePlugin" }

và chỉ định các biến đã tạo trong tệp bản dựng:

Kotlin

// In a module-level build script
// Using a version catalog
plugins {
    alias(libs.plugins.example.plugin)
}

dependencies {
    implementation(libs.example.library)
}

Groovy

// In a module-level build script
// Using a version catalog
plugins {
    alias(libs.plugins.example.plugin)
}

dependencies {
    implementation libs.example.library
}