Android KTX   Android Jetpack 的一部分。

Android KTX 是一套包含在 Android Jetpack 和其他 Android 库中的 Kotlin 扩展程序。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 Core 函数之一的示例,SharedPreferences.edit,它向 SharedPreferences 添加了一个 edit 函数。此函数将其第一个参数作为可选的 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.15.0"
}

Kotlin

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

以下是核心 KTX 模块中包含的包列表:

集合 KTX

集合扩展程序包含用于处理 Android 的内存高效集合库(包括 ArrayMapLongSparseArrayLruCache 等)的实用程序函数。

要使用此模块,请将以下内容添加到应用的 build.gradle 文件中:

Groovy

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

Kotlin

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

集合扩展程序利用 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

Fragment KTX

Fragment KTX 模块 提供了许多扩展程序,可以简化 Fragment API。

要包含此模块,请将以下内容添加到应用的 build.gradle 文件中:

Groovy

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

Kotlin

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

使用 Fragment KTX 模块,您可以使用 lambda 表达式简化 Fragment 事务,例如:

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

Lifecycle KTX

Lifecycle KTX 为每个 Lifecycle 对象定义了一个 LifecycleScope。在此作用域中启动的任何协程都会在 Lifecycle 被销毁时取消。您可以使用 lifecycle.coroutineScopelifecycleOwner.lifecycleScope 属性访问 LifecycleCoroutineScope

要包含此模块,请将以下内容添加到应用的 build.gradle 文件中:

Groovy

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

Kotlin

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

以下示例演示如何使用 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 时,您可能需要异步计算值。例如,您可能希望检索用户的偏好设置并将其提供给您的 UI。对于这些情况,LiveData KTX 提供了一个 liveData 构建器函数,该函数调用一个 suspend 函数并将结果作为 LiveData 对象提供。

要包含此模块,请将以下内容添加到应用的 build.gradle 文件中:

Groovy

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

Kotlin

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

在以下示例中,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.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")
}

使用扩展函数和属性委托访问目标参数并导航到目标,如下例所示

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 模块 提供了用于处理调色板的惯用的 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 运算符 ([ ]) 为给定的 target 检索 selected 样本。

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

Reactive Streams KTX

Reactive Streams KTX 模块允许您从 ReactiveStreams 发布者创建一个可观察的 LiveData 流。

要包含此模块,请将以下内容添加到应用的 build.gradle 文件中:

Groovy

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

Kotlin

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

例如,假设一个包含少量用户列表的数据库。在您的应用中,您将数据库加载到内存中,然后在您的 UI 中显示用户数据。为此,您可以使用 RxJavaRoom Jetpack 组件可以将用户列表检索为 Flowable。在这种情况下,您还必须在片段或活动的整个生命周期中管理 Rx 发布者订阅。

但是,使用 LiveDataReactiveStreams,您可以从 RxJava 及其丰富的运算符和工作调度功能中受益,同时还可以使用 LiveData 的简易性,如下例所示

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

Room KTX

Room 扩展添加了对数据库事务的协程支持。

要使用此模块,请将以下内容添加到应用的 build.gradle 文件中:

Groovy

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

Kotlin

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

以下是一些 Room 现在使用协程的示例。第一个示例使用 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.4.0"
}

Kotlin

dependencies {
    implementation("androidx.sqlite:sqlite-ktx:2.4.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.8.7"
}

Kotlin

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

例如,以下 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.9.1"
}

Kotlin

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

您可以扩展 CoroutineWorker(它具有略微不同的 API),而不是扩展 Worker。例如,如果您想构建一个简单的 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 以挂起当前协程。

这是一个挂起 Operation 的示例,该 Operationenqueue() 返回

// 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 Maps Platform KTX

Google Maps Platform Android SDK 提供了 KTX 扩展,使您可以利用多种 Kotlin 语言特性,例如扩展函数、命名参数和默认参数、解构声明和协程。有关更多信息,请参阅以下主题

Play Core KTX

Play Core KTX 通过向 Play Core 库中的 SplitInstallManagerAppUpdateManager 添加扩展函数,为一次性请求添加了对 Kotlin 协程的支持,并为监控状态更新添加了对 Flow 的支持。

要包含此模块,请将以下内容添加到应用的 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 问题跟踪器