Android KTX   Một phần của Android Jetpack.

Android KTX là một tập hợp các tiện ích của Kotlin, có trong Android Jetpack và các thư viện Android khác. Các tiện ích KTX cung cấp mã nguồn ngắn gọn và tương thích với ngôn ngữ Kotlin để truy cập Jetpack, nền tảng Android và các API khác. Để làm được như vậy, những tiện ích này tận dụng một số tính năng của ngôn ngữ Kotlin, bao gồm:

  • Hàm mở rộng
  • Thuộc tính mở rộng
  • Hàm lambda
  • Tham số được đặt tên
  • Giá trị mặc định của tham số
  • Coroutine

Ví dụ: khi làm việc với SharedPreferences, bạn phải tạo trình chỉnh sửa thì mới có thể sửa đổi dữ liệu về tuỳ chọn. Bạn cũng phải áp dụng hoặc lưu những thay đổi đó khi đã chỉnh sửa xong, như trong ví dụ sau:

sharedPreferences
        .edit()  // create an Editor
        .putBoolean("key", value)
        .apply() // write to disk asynchronously

Hàm lambda của Kotlin rất phù hợp cho trường hợp sử dụng này. Hàm lambda cho phép bạn sử dụng mã nguồn ngắn gọn hơn bằng cách truyền một khối mã để thực thi sau khi tạo trình chỉnh sửa, qua đó cho phép thực thi mã và sau đó để API SharedPreferences áp dụng đồng loạt các thay đổi.

Dưới đây là ví dụ về một trong các hàm cốt lõi của Android KTX, SharedPreferences.edit, có chức năng thêm hàm chỉnh sửa vào SharedPreferences. Hàm này sẽ lấy một cờ boolean tuỳ chọn làm đối số đầu tiên để cho biết liệu có cần lưu hay áp dụng các thay đổi hay không. Hàm này cũng nhận một hành động để thực hiện trên trình chỉnh sửa SharedPreferences dưới dạng một lambda.

// SharedPreferences.edit extension function signature from Android KTX - Core
// inline fun SharedPreferences.edit(
//         commit: Boolean = false,
//         action: SharedPreferences.Editor.() -> Unit)

// Commit a new value asynchronously
sharedPreferences.edit { putBoolean("key", value) }

// Commit a new value synchronously
sharedPreferences.edit(commit = true) { putBoolean("key", value) }

Phương thức gọi (caller) có thể chọn lưu hoặc áp dụng các thay đổi. Hàm lambda action là một hàm mở rộng ẩn danh trên SharedPreferences.Editor, trình chỉnh sửa này trả về Unit, như được chỉ định bằng chữ ký. Vì vậy, trong khối (block) này, bạn có thể thực hiện tác vụ ngay trên SharedPreferences.Editor.

Cuối cùng, chữ ký SharedPreferences.edit() chứa từ khoá inline. Từ khoá này cho trình biên dịch Kotlin biết rằng nên sao chép và dán (hoặc đưa vào cùng dòng) mã byte đã biên dịch cho hàm này mỗi lần hàm được sử dụng. Việc này giúp tránh tiêu tốn tài nguyên để tạo bản sao lớp mới cho từng action mỗi khi hàm này được gọi.

Mẫu truyền mã này sử dụng lambda áp dụng các giá trị mặc định hợp lý có thể bị ghi đè và thêm các hành vi này vào các API hiện có bằng cách sử dụng các hàm mở rộng inline. Đây là ví dụ điển hình cho thấy các tính năng nâng cao mà thư viện Android KTX đem lại.

Sử dụng Android KTX trong dự án của bạn

Để bắt đầu sử dụng Android KTX, hãy thêm phần phụ thuộc sau vào tệp build.gradle của dự án:

Groovy

repositories {
    google()
}

Kotlin

repositories {
    google()
}

Các mô-đun AndroidX

Android KTX được sắp xếp thành nhiều mô-đun, trong đó mỗi mô-đun chứa một hoặc nhiều gói.

Bạn phải đưa phần phụ thuộc của từng cấu phần phần mềm mô-đun vào tệp build.gradle của ứng dụng. Hãy nhớ thêm số phiên bản vào cấu phần phần mềm. Bạn có thể tìm thấy số phiên bản mới nhất trong phần tương ứng của mỗi cấu phần phần mềm trong chủ đề này.

Android KTX chứa một mô-đun cốt lõi duy nhất cung cấp các tiện ích của Kotlin cho các API khung phổ biến và một số tiện ích dành riêng cho từng miền.

Ngoại trừ mô-đun cốt lõi, tất cả cấu phần phần mềm KTX đều thay thế phần phụ thuộc Java cơ bản trong tệp build.gradle của bạn. Ví dụ: bạn có thể thay thế phần phụ thuộc androidx.fragment:fragment bằng androidx.fragment:fragment-ktx. Cú pháp này giúp quản lý phiên bản tốt hơn và không yêu cầu phải khai báo thêm cho phần phụ thuộc.

Core KTX

Core KTX (mô-đun KTX cốt lõi) cung cấp tiện ích cho những thư viện phổ biến trong khung Android. Các thư viện này không có phần phụ thuộc bằng Java mà bạn phải thêm vào build.gradle.

Để thêm mô-đun này, hãy thêm nội dung sau vào tệp build.gradle của ứng dụng:

Groovy

dependencies {
    implementation "androidx.core:core-ktx:1.15.0"
}

Kotlin

dependencies {
    implementation("androidx.core:core-ktx:1.15.0")
}

Dưới đây là danh sách các gói có trong mô-đun Core KTX:

Collection KTX

Tiện ích Collection KTX chứa các hàm số hiệu dụng để làm việc với các thư viện của Android về tập hợp tiết kiệm bộ nhớ, bao gồm ArrayMap, LongSparseArray, LruCache, v.v.

Để sử dụng mô-đun này, hãy thêm nội dung sau vào tệp build.gradle của ứng dụng:

Groovy

dependencies {
    implementation "androidx.collection:collection-ktx:1.4.5"
}

Kotlin

dependencies {
    implementation("androidx.collection:collection-ktx:1.4.5")
}

Mô-đun tiện ích về tập hợp tận dụng cơ chế nạp chồng toán tử của Kotlin để đơn giản hoá những công việc như nối tập hợp, như trong ví dụ sau:

// Combine 2 ArraySets into 1.
val combinedArraySet = arraySetOf(1, 2, 3) + arraySetOf(4, 5, 6)

// Combine with numbers to create a new sets.
val newArraySet = combinedArraySet + 7 + 8

Fragment KTX

Fragment KTX (mô-đun mảnh KTX) cung cấp một số tiện ích để đơn giản hoá API mảnh.

Để thêm mô-đun này, hãy thêm nội dung sau vào tệp build.gradle của ứng dụng:

Groovy

dependencies {
    implementation "androidx.fragment:fragment-ktx:1.8.3"
}

Kotlin

dependencies {
    implementation("androidx.fragment:fragment-ktx:1.8.3")
}

Thông qua mô-đun mảnh của KTX, bạn có thể đơn giản hoá các giao dịch mảnh bằng hàm lambda, ví dụ:

fragmentManager().commit {
   addToBackStack("...")
   setCustomAnimations(
           R.anim.enter_anim,
           R.anim.exit_anim)
   add(fragment, "...")
}

Bạn cũng có thể liên kết với ViewModel trong một dòng bằng cách sử dụng trình uỷ quyền thuộc tính viewModelsactivityViewModels:

// Get a reference to the ViewModel scoped to this Fragment
val viewModel by viewModels<MyViewModel>()

// Get a reference to the ViewModel scoped to its Activity
val viewModel by activityViewModels<MyViewModel>()

Lifecycle KTX

Lifecycle KTX (mô-đun vòng đời của KTX) xác định một LifecycleScope cho mỗi đối tượng Lifecycle. Mọi coroutine khởi chạy trong phạm vi này sẽ tự động huỷ khi Lifecycle bị huỷ bỏ. Bạn có thể truy cập vào CoroutineScope của Lifecycle thông qua thuộc tính lifecycle.coroutineScope hoặc thuộc tính lifecycleOwner.lifecycleScope.

Để thêm mô-đun này, hãy thêm nội dung sau vào tệp build.gradle của ứng dụng:

Groovy

dependencies {
    implementation "androidx.lifecycle:lifecycle-runtime-ktx:2.8.7"
}

Kotlin

dependencies {
    implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.8.7")
}

Ví dụ sau minh hoạ cách sử dụng lifecycleOwner.lifecycleScope để tạo văn bản được tính toán trước một cách không đồng bộ:

class MyFragment: Fragment() {
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        viewLifecycleOwner.lifecycleScope.launch {
            val params = TextViewCompat.getTextMetricsParams(textView)
            val precomputedText = withContext(Dispatchers.Default) {
                PrecomputedTextCompat.create(longTextContent, params)
            }
            TextViewCompat.setPrecomputedText(textView, precomputedText)
        }
    }
}

LiveData của KTX

Khi sử dụng LiveData, bạn có thể sẽ phải tính toán các giá trị một cách không đồng bộ. Ví dụ: bạn có thể sẽ muốn truy xuất các tuỳ chọn của người dùng và phân phát các tuỳ chọn đó đến giao diện người dùng của bạn. Đối với những trường hợp như vậy, LiveData của KTX cung cấp hàm tạo liveData để gọi hàm suspend và cung cấp kết quả dưới dạng đối tượng LiveData.

Để thêm mô-đun này, hãy thêm nội dung sau vào tệp build.gradle của ứng dụng:

Groovy

dependencies {
    implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.8.7"
}

Kotlin

dependencies {
    implementation("androidx.lifecycle:lifecycle-livedata-ktx:2.8.7")
}

Trong ví dụ sau, loadUser() là hàm tạm ngưng được khai báo ở nơi khác. Bạn có thể sử dụng hàm tạo liveData để gọi loadUser() một cách không đồng bộ, rồi sử dụng emit() để phát kết quả:

val user: LiveData<User> = liveData {
    val data = database.loadUser() // loadUser is a suspend function.
    emit(data)
}

Để biết thêm thông tin về việc sử dụng coroutine qua LiveData, hãy xem phần Sử dụng coroutine thông qua các thành phần Kiến trúc.

Mỗi thành phần của thư viện Điều hướng (Navigation) đều có phiên bản KTX riêng để điều chỉnh API sao cho ngắn gọn hơn và tương thích với Kotlin.

Để đưa các mô-đun này vào, hãy thêm nội dung sau vào tệp build.gradle của ứng dụng:

Groovy

dependencies {
    implementation "androidx.navigation:navigation-runtime-ktx:2.8.4"
    implementation "androidx.navigation:navigation-fragment-ktx:2.8.4"
    implementation "androidx.navigation:navigation-ui-ktx:2.8.4"
}

Kotlin

dependencies {
    implementation("androidx.navigation:navigation-runtime-ktx:2.8.4")
    implementation("androidx.navigation:navigation-fragment-ktx:2.8.4")
    implementation("androidx.navigation:navigation-ui-ktx:2.8.4")
}

Sử dụng các hàm mở rộng và uỷ quyền thuộc tính để truy cập vào các đối số đích và điều hướng đến đích như trong ví dụ sau:

class MyDestination : Fragment() {

    // Type-safe arguments are accessed from the bundle.
    val args by navArgs<MyDestinationArgs>()

    ...
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        view.findViewById<Button>(R.id.next)
            .setOnClickListener {
                // Fragment extension added to retrieve a NavController from
                // any destination.
                findNavController().navigate(R.id.action_to_next_destination)
            }
     }
     ...

}

Palette KTX

Palette KTX (mô-đun Bảng màu của KTX) cung cấp hỗ trợ tương thích với Kotlin để xử lý bảng màu.

Để sử dụng mô-đun này, hãy thêm nội dung sau vào tệp build.gradle của ứng dụng:

Groovy

dependencies {
    implementation "androidx.palette:palette-ktx:1.0.0"
}

Kotlin

dependencies {
    implementation("androidx.palette:palette-ktx:1.0.0")
}

Ví dụ: khi làm việc với một thực thể Palette, bạn có thể truy xuất mẫu màu selected cho một target nhất định bằng cách sử dụng toán tử nhận ([ ]):

val palette = Palette.from(bitmap).generate()
val swatch = palette[target]

Reactive Streams KTX

Reactive Streams KTX (mô-đun luồng phản ứng) của KTX cho phép bạn tạo luồng LiveData quan sát được từ trình xuất bản ReactiveStreams.

Để thêm mô-đun này, hãy thêm nội dung sau vào tệp build.gradle của ứng dụng:

Groovy

dependencies {
    implementation "androidx.lifecycle:lifecycle-reactivestreams-ktx:2.8.7"
}

Kotlin

dependencies {
    implementation("androidx.lifecycle:lifecycle-reactivestreams-ktx:2.8.7")
}

Ví dụ: giả sử một cơ sở dữ liệu có một danh sách nhỏ chứa người dùng. Trong ứng dụng, bạn tải cơ sở dữ liệu vào bộ nhớ, sau đó hiện dữ liệu người dùng trong giao diện người dùng. Để làm được điều này, bạn có thể sử dụng RxJava. Thành phần Room của Jetpack có thể truy xuất danh sách người dùng dưới dạng Flowable. Trong trường hợp này, bạn cũng phải quản lý đối tượng theo dõi của trình xuất bản Rx trong suốt vòng đời của mảnh hoặc hoạt động của bạn.

Tuy nhiên, thông qua LiveDataReactiveStreams, bạn có thể hưởng lợi từ RxJava cùng với rất nhiều các toán tử và khả năng lên lịch tác vụ, bạn cũng đồng thời tận hưởng sự đơn giản của LiveData, như trong ví dụ sau:

val fun getUsersLiveData() : LiveData<List<User>> {
    val users: Flowable<List<User>> = dao.findUsers()
    return LiveDataReactiveStreams.fromPublisher(users)
}

Room KTX

Các tiện ích về Room (không gian) giúp tăng cường hỗ trợ coroutine cho các giao dịch cơ sở dữ liệu.

Để sử dụng mô-đun này, hãy thêm nội dung sau vào tệp build.gradle của ứng dụng:

Groovy

dependencies {
    implementation "androidx.room:room-ktx:2.6.1"
}

Kotlin

dependencies {
    implementation("androidx.room:room-ktx:2.6.1")
}

Dưới đây là một số ví dụ trong đó Room sử dụng coroutine. Ví dụ đầu tiên sử dụng hàm suspend để trả về danh sách các đối tượng User, còn ví dụ thứ hai sử dụng Flow của Kotlin để trả về danh sách User một cách không đồng bộ. Lưu ý rằng khi sử dụng Flow, bạn cũng sẽ được thông báo về mọi thay đổi trong các bảng mà bạn đang truy vấn.

@Query("SELECT * FROM Users")
suspend fun getUsers(): List<User>

@Query("SELECT * FROM Users")
fun getUsers(): Flow<List<User>>

SQLite KTX

Các tiện ích về SQLite bao bọc mã liên quan đến SQL trong các giao dịch, giúp loại bỏ rất nhiều mã nguyên mẫu.

Để sử dụng mô-đun này, hãy thêm nội dung sau vào tệp build.gradle của ứng dụng:

Groovy

dependencies {
    implementation "androidx.sqlite:sqlite-ktx:2.4.0"
}

Kotlin

dependencies {
    implementation("androidx.sqlite:sqlite-ktx:2.4.0")
}

Dưới đây là ví dụ về cách sử dụng tiện ích về transaction để thực hiện giao dịch cơ sở dữ liệu:

db.transaction {
    // insert data
}

ViewModel KTX

Thư viện ViewModel KTX cung cấp hàm viewModelScope() giúp bạn dễ dàng chạy coroutine từ ViewModel của mình. CoroutineScope được liên kết với Dispatchers.Main và tự động bị huỷ khi ViewModel bị xoá. Bạn có thể sử dụng viewModelScope() thay vì tạo phạm vi mới cho mỗi ViewModel.

Để thêm mô-đun này, hãy thêm nội dung sau vào tệp build.gradle của ứng dụng:

Groovy

dependencies {
    implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.8.5"
}

Kotlin

dependencies {
    implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.8.5")
}

Ví dụ: hàm viewModelScope() sau đây sẽ khởi chạy một coroutine thực hiện yêu cầu mạng trong một luồng trong nền. Thư viện xử lý tất cả các bước thiết lập và xoá phạm vi tương ứng:

class MainViewModel : ViewModel() {
    // Make a network request without blocking the UI thread
    private fun makeNetworkRequest() {
        // launch a coroutine in viewModelScope
        viewModelScope.launch  {
            remoteApi.slowFetch()
            ...
        }
    }

    // No need to override onCleared()
}

WorkManager KTX

WorkManager của KTX cung cấp hỗ trợ hàng đầu cho coroutine.

Để thêm mô-đun này, hãy thêm nội dung sau vào tệp build.gradle của ứng dụng:

Groovy

dependencies {
    implementation "androidx.work:work-runtime-ktx:2.9.1"
}

Kotlin

dependencies {
    implementation("androidx.work:work-runtime-ktx:2.9.1")
}

Thay vì mở rộng Worker, giờ đây, bạn có thể mở rộng CoroutineWorker với một API hơi khác một chút. Ví dụ: nếu muốn tạo một CoroutineWorker đơn giản để thực hiện một số thao tác mạng, bạn có thể làm như sau:

class CoroutineDownloadWorker(context: Context, params: WorkerParameters)
        : CoroutineWorker(context, params) {

    override suspend fun doWork(): Result = coroutineScope {
        val jobs = (0 until 100).map {
            async {
                downloadSynchronously("https://www.google.com")
            }
        }

        // awaitAll will throw an exception if a download fails, which
        // CoroutineWorker will treat as a failure
        jobs.awaitAll()
        Result.success()
    }
}

Để biết thêm thông tin về cách sử dụng CoroutineWorker, hãy xem Tạo luồng trong CoroutineWorker.

WorkManager của KTX cũng thêm các hàm mở rộng vào OperationsListenableFutures để tạm ngưng coroutine hiện tại.

Dưới đây là ví dụ về việc tạm ngưng Operationenqueue() trả về:

// Inside of a coroutine...

// Run async operation and suspend until completed.
WorkManager.getInstance()
        .beginWith(longWorkRequest)
        .enqueue().await()

// Resume after work completes...

Các mô-đun KTX khác

Bạn cũng có thể thêm các mô-đun KTX bổ sung tồn tại bên ngoài AndroidX.

Firebase KTX

Một số SDK của Firebase cho Android có thư viện tiện ích cho Kotlin, các thư viện này cho phép bạn viết mã Kotlin khi sử dụng Firebase trong ứng dụng của bạn. Để biết thêm thông tin, hãy xem các chủ đề sau:

Google Maps Platform KTX

Hiện đã có mô-đun chức năng KTX mở rộng cho các SDK Android của Nền tảng Google Maps, cho phép bạn tận dụng một số tính năng của ngôn ngữ Kotlin như hàm mở rộng, tham số được đặt tên và đối số mặc định, khai báo trích xuất và coroutine. Để biết thêm thông tin, hãy xem các chủ đề sau:

Play Core KTX

Play Core của KTX hỗ trợ thêm coroutine của Kotlin cho các yêu cầu một lần và Flow (dòng dữ liệu), giúp theo dõi thông tin cập nhật về trạng thái bằng cách thêm hàm mở rộng vào SplitInstallManagerAppUpdateManager trong thư viện Play Core.

Để thêm mô-đun này, hãy thêm nội dung sau vào tệp build.gradle của ứng dụng:

Groovy

dependencies {
    implementation "com.google.android.play:core-ktx:1.8.1"
}

Kotlin

dependencies {
    implementation("com.google.android.play:core-ktx:1.8.1")
}

Dưới đây là ví dụ về Flow theo dõi trạng thái:

// Inside of a coroutine...

// Request in-app update status updates.
manager.requestUpdateFlow().collect { updateResult ->
    when (updateResult) {
        is AppUpdateResult.Available -> TODO()
        is AppUpdateResult.InProgress -> TODO()
        is AppUpdateResult.Downloaded -> TODO()
        AppUpdateResult.NotAvailable -> TODO()
    }
}

Thông tin khác

Để tìm hiểu thêm về Android KTX, hãy xem video DevBytes.

Để báo cáo sự cố hoặc đề xuất tính năng, hãy sử dụng trình theo dõi sự cố của Android KTX.