Android KTX   Android Jetpack 的一部分。

Android KTX 是一組 Kotlin 擴充功能,隨附於 Android Jetpack 及其他 Android 程式庫中。KTX 擴充功能可為 Jetpack、Android 平台和其他 API 提供簡潔、符合語言習慣的 Kotlin 語言。為此,這些擴充功能使用多個 Kotlin 語言功能,包括:

  • 擴充功能函式
  • 擴充功能屬性
  • Lambda
  • 已命名參數
  • 參數預設值
  • 協同程式

例如,在使用 SharedPreferences 時,您必須先建立編輯器,才能修改偏好設定資料。完成編輯後,您還必須套用或修訂這些變更,如以下範例所示:

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

Kotlin lambda 非常適合這個用途。這些值可讓您採取更簡潔的做法,即在建立編輯器後,傳遞要執行的程式碼區塊,讓程式碼執行,再讓 SharedPreferences API 自動套用變更。

下文以其中一個 Android KTX 核心函式 SharedPreferences.edit 為例。該函式會將編輯函式新增至 SharedPreferences。該函式將選用 boolean 旗標視為第一個引數,藉此指明是否要修訂或套用變更。該函式也收到要在採用 lambda 格式的 SharedPreferences 編輯器上執行的動作。

// 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) }

呼叫端可選擇是否修訂或套用變更。action lambda 本身是 SharedPreferences.Editor 上的匿名擴充功能函式,可傳回 Unit,如其簽名所示。因此,您可以在區塊內直接透過 SharedPreferences.Editor 執行工作。

最後,SharedPreferences.edit() 簽名包含 inline 關鍵字。這個關鍵字向 Kotlin 編譯器傳達的訊息是,每次使用函式時,編譯器應該為函式複製及貼上 (或「內嵌」) 經過編譯的位元碼。在每次呼叫此函式時,這樣可避免產生為每個 action 的新類別進行執行個體化作業所需的額外負荷。

此模式使用 lambda 傳遞程式碼,套用可覆寫的合理預設值,並透過 inline 擴充功能函式將這些行為新增至現有 API,所以通常能達到 Android KTX 程式庫提供的增強效果。

在專案中使用 Android KTX

如要開始使用 Android KTX,請將以下依附元件新增至專案的 build.gradle 檔案:

Groovy

repositories {
    google()
}

Kotlin

repositories {
    google()
}

AndroidX 模組

Android KTX 分為多個模組,每個模組都包含一個或多個套件。

您必須在應用程式的 build.gradle 檔案中加入每個模組成果的依附元件。請記得在成果中附加版本號碼。在這個主題中,每個成果的相應章節均會顯示最新的版本號碼。

Android KTX 包含單一核心模組,可為一般架構 API 和數個特定領域的擴充功能提供 Kotlin 擴充功能。

除了核心模組外,所有 KTX 模組成果都會取代 build.gradle 檔案的基礎 Java 依附元件。例如,您可以將 androidx.fragment:fragment 依附元件替換為 androidx.fragment:fragment-ktx。這個語法不但能促進版本管理,也不必新增其他依附元件宣告要求。

核心 KTX

核心 KTX 模組為組成 Android 架構的常見程式庫提供擴充功能。這些程式庫沒有需要新增至 build.gradle 的 Java 依附元件。

如要加入這個模組,請在應用程式的 build.gradle 檔案中新增以下程式碼:

Groovy

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

Kotlin

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

以下是核心 KTX 模組中包含的套件清單:

集合 KTX

集合擴充功能含有公用函式。這些函式可使用 Android 的高效記憶體集合程式庫,包括 ArrayMapLongSparseArrayLruCache 等。

如要使用這個模組,請在應用程式的 build.gradle 檔案中新增以下程式碼:

Groovy

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

Kotlin

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

集合擴充功能利用 Kotlin 的運算子超載,來簡化集合串連和其他作業,如以下範例所示:

// 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

片段 KTX

片段 KTX 模組提供許多擴充功能來簡化片段 API。

如要加入這個模組,請在應用程式的 build.gradle 檔案中新增以下程式碼:

Groovy

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

Kotlin

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

透過 Fragment KTX 模組,您可以使用 lambda 簡化片段交易,例如:

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

您也可以使用 viewModelsactivityViewModels 屬性委派,繫結至同一行中的 ViewModel

// 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>()

生命週期 KTX

生命週期 KTX 為每個 Lifecycle 物件定義 LifecycleScope。刪除 Lifecycle 時,系統會取消在此範圍內啟動的任何協同程式。您可以使用 lifecycle.coroutineScopelifecycleOwner.lifecycleScope 屬性,來存取 LifecycleCoroutineScope

如要加入這個模組,請在應用程式的 build.gradle 檔案中新增以下程式碼:

Groovy

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

Kotlin

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

以下範例說明如何使用 lifecycleOwner.lifecycleScope,來非同步建立預先計算的文字:

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 KTX

使用 LiveData 時,您可能需要非同步計算值。例如,您可能想擷取使用者的偏好設定,並將這些偏好設定提供給您的使用者介面。對於這些情況,LiveData KTX 會提供 liveData 建構工具函式。該函式用於呼叫 suspend 函式,並提供結果,用做 LiveData 物件。

如要加入這個模組,請在應用程式的 build.gradle 檔案中新增以下程式碼:

Groovy

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

Kotlin

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

在以下範例中,loadUser() 是已在其他位置宣告的暫停函式。您可以使用 liveData 建構工具函式,以非同步方式呼叫 loadUser(),然後使用 emit() 發出結果:

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

如要進一步瞭解如何搭配 LiveData 使用協同程式,請參閱「將 Kotlin 協同程式與架構元件搭配使用」一文。

導覽程式庫的每個元件都有自身的 KTX 版本。該版本可將 API 調整為較精簡且符合 Kotlin 的語言習慣。

如要加入這些模組,請在應用程式的 build.gradle 檔案中新增以下程式碼:

Groovy

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

Kotlin

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

使用擴充功能函式和屬性委派,即可存取目的地引數,並前往目的地,如以下範例所示:

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)
            }
     }
     ...

}

區塊面板 KTX

區塊面板 KTX 模組提供符合語言習慣的 Kotlin 支援,以便使用調色盤。

如要使用這個模組,請在應用程式的 build.gradle 檔案中新增以下程式碼:

Groovy

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

Kotlin

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

例如,使用 Palette 執行個體時,您可以透過 get 運算子 ([ ]) 擷取特定 targetselected 樣本:

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

回應式串流 KTX

回應式串流 KTX 模組可從 ReactiveStreams 發布者建立可觀測的 LiveData 串流。

如要加入這個模組,請在應用程式的 build.gradle 檔案中新增以下程式碼:

Groovy

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

Kotlin

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

例如,假設資料庫中只有一小群使用者。在應用程式中,您將資料庫載入記憶體,然後在使用者介面中顯示使用者資料。為達成此目標,您可以使用 RxJavaRoom Jetpack 元件可將使用者清單擷取為 Flowable。在這種情況下,您還必須在片段或活動的整個生命週期內管理 Rx 發布者的訂閱項目。

不過,LiveDataReactiveStreams 可讓您享有 RxJava 及其豐富的運算子和工作排程功能,同時也能輕鬆使用 LiveData,如以下範例所示:

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

聊天室 KTX

聊天室擴充功能為資料庫交易加入協同程式支援。

如要使用這個模組,請在應用程式的 build.gradle 檔案中新增以下程式碼:

Groovy

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

Kotlin

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

以下列舉幾種聊天室目前使用協同程式的情況。第一個範例使用 suspend 函式,傳回 User 物件清單,而第二個範例利用 Kotlin 的Flow,以非同步方式傳回 User 清單。請注意,在使用 Flow 時,系統也會在您查詢的資料表發生任何變更時通知您。

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

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

SQLite KTX

SQLite 擴充功能會將 SQL 相關程式碼納入交易中,並且消除大量樣板程式碼。

如要使用這個模組,請在應用程式的 build.gradle 檔案中新增以下程式碼:

Groovy

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

Kotlin

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

以下範例說明,如何使用 transaction 擴充功能執行資料庫交易:

db.transaction {
    // insert data
}

ViewModel KTX

ViewModel KTX 程式庫提供 viewModelScope() 函式,藉此更容易從 ViewModel 啟動協同程式CoroutineScope 被繫結至 Dispatchers.Main,且在清除 ViewModel 時自動取消。您可以使用 viewModelScope(),而不是為每個 ViewModel 建立新的範圍。

如要加入這個模組,請在應用程式的 build.gradle 檔案中新增以下程式碼:

Groovy

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

Kotlin

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

例如,以下 viewModelScope() 函式會啟動一個協同程式。該協同程式會在背景執行緒中發出網路要求。程式庫會處理所有設定和相應的範圍清除作業:

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 KTX 為協同程式提供一流的支援。

如要加入這個模組,請在應用程式的 build.gradle 檔案中新增以下程式碼:

Groovy

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

Kotlin

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

您不必擴充 Worker,只要擴充 CoroutineWorker (其 API 稍有不同) 即可。例如,如果您想建構簡單的 CoroutineWorker,來執行某些網路作業,您可以執行以下動作:

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()
    }
}

如要進一步瞭解如何使用 CoroutineWorker,請參閱「CoroutineWorker 中的執行緒」一文。

WorkManager KTX 也會將擴充功能函式新增至 OperationsListenableFutures,以暫停當前的協同程式。

以下範例說明,如何暫停 enqueue() 傳回的 Operation

// Inside of a coroutine...

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

// Resume after work completes...

其他 KTX 模組

您也可以加入 AndroidX 以外的其他 KTX 模組。

Firebase KTX

有些 Android 版 Firebase SDK 包含 Kotlin 擴充功能程式庫,可讓您在應用程式中使用 Firebase 時編寫符合語言習慣的 Kotlin 程式碼。詳情請參閱下列主題:

Google 地圖平台 KTX

Google 地圖平台 Android SDK 可使用 KTX 擴充功能。這些 SDK 可讓您充分利用幾種 Kotlin 語言功能,例如擴充功能函式、已命名參數和預設引數、刪除宣告和協同程式。詳情請參閱下列主題:

Play Core KTX

Play Core KTX 透過在 Play Core 程式庫的 SplitInstallManagerAppUpdateManager 中新增擴充功能函式,為一次性請求和用於監控狀態更新的資料流,新增對 Kotlin 協同程式的支援。

如要加入這個模組,請在應用程式的 build.gradle 檔案中新增以下程式碼:

Groovy

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

Kotlin

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

以下是狀態監控 Flow 的範例:

// 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()
    }
}

更多資訊

如要進一步瞭解 Android KTX,請參閱 DevBytes 影片

如要回報問題或提出功能建議,請使用 Android KTX Issue Tracker