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.13.1" }
Kotlin
dependencies { implementation("androidx.core:core-ktx:1.13.1") }
Dưới đây là danh sách các gói có trong mô-đun Core KTX:
- androidx.core.animation
- androidx.core.content
- androidx.core.content.res
- androidx.core.database
- androidx.core.database.sqlite
- androidx.core.graphics
- androidx.core.graphics.drawable
- androidx.core.location
- androidx.core.net
- androidx.core.os
- androidx.core.text
- androidx.core.transition
- androidx.core.util
- androidx.core.view
- androidx.core.widget
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 viewModels
và
activityViewModels
:
// 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.
Navigation KTX
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 Operations
và
ListenableFutures
để tạm ngưng coroutine hiện tại.
Dưới đây là ví dụ về việc tạm ngưng
Operation
mà enqueue()
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 SplitInstallManager
và AppUpdateManager
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.