一、Android KTX 简介
Android KTX 是包含在 Android Jetpack 及其他 Android 库 中的一组 Kotlin 扩展程序 。KTX 扩展程序可以为 Jetpack、Android 平台及其他 API 提供简洁的惯用 Kotlin 代码。为此,这些扩展程序利用了多种 Kotlin 语言功能,其中包括:扩展函数、扩展属性、Lambda、命名参数、参数默认值、协程 。
使用 lambda 传递代码 、使用可以替换的合理默认值 ,使用 inline 扩展函数,将这些行为添加到现有 API 中,这种模式是 Android KTX 库提供的典型增强功能。
cpp
复制代码
// 未使用 Android KTX 前实现模式
sharedPreferences
.edit() // create an Editor
.putBoolean("key", value)
.apply() // write to disk asynchronously
// Android KTX 模式
// 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) }
SharedPreferences.edit() 方法包含 inline 关键字 。此关键字向 Kotlin 编译器表明,每次使用函数时,它都应该为函数复制并粘贴 (或内嵌)编译的字节码。这样可避免每次调用此函数时都为每个 action 实例化一个新类所产生的开销。
二、AndroidX 模块
Android KTX 分为若干模块,每个模块包含一个或多个软件包。
必须在应用的 build.gradle 文件中为每个模块添加一个依赖项,并在模块后面附上版本号。
Android KTX 包含一个核心模块,该模块可为通用框架 API 提供 Kotlin 扩展程序,而且还能提供一些领域专用的扩展程序。
除了核心模块之外,所有 KTX 模块都会替换 build.gradle 文件中的底层 Java 依赖项。例如,您可以将 androidx.fragment:fragment 依赖项替换为 androidx.fragment:fragment-ktx。
1、Core KTX
Core KTX 模块为 Android 框架的通用库 提供扩展程序。
要使用此模块,需在应用的 build.gradle 文件中添加相应的依赖项。
cpp
复制代码
dependencies {
implementation("androidx.core:core-ktx:1.16.0")
}
下面列出了 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
2、Collection KTX
Collection 扩展程序包含集合库(在Android 中节省内存的)中使用的实用函数,包括 ArrayMap、LongSparseArray、LruCache 等等。
要使用此模块,需在应用的 build.gradle 文件中添加相应的依赖项。
cpp
复制代码
dependencies {
implementation("androidx.collection:collection-ktx:1.3.0")
}
Collection 扩展程序利用 Kotlin 的运算符重载简化集合串联等操作
cpp
复制代码
// 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
3、Fragment KTX
Fragment KTX 模块提供了一系列扩展程序以简化 Fragment API。
要使用此模块,需在应用的 build.gradle 文件中添加相应的依赖项。
cpp
复制代码
dependencies {
implementation("androidx.fragment:fragment-ktx:1.6.2")
}
借助 Fragment KTX 模块,可以使用 lambda 来简化 Fragment 事务。
cpp
复制代码
fragmentManager().commit {
addToBackStack("...")
setCustomAnimations(
R.anim.enter_anim,
R.anim.exit_anim)
add(fragment, "...")
}
还可以使用 viewModels 和 activityViewModels 属性委托在一行中绑定到 ViewModel。
cpp
复制代码
// 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>()
4、Lifecycle KTX
Lifecycle KTX 为每个 Lifecycle 对象定义一个 LifecycleScope。在此范围内启动的协程会在 Lifecycle 被销毁时取消。您可以使用 lifecycle.coroutineScope 或 lifecycleOwner.lifecycleScope 属性访问 Lifecycle 的 CoroutineScope。
要使用此模块,需在应用的 build.gradle 文件中添加相应的依赖项。
cpp
复制代码
dependencies {
implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.6.2")
}
使用 lifecycleOwner.lifecycleScope 异步创建预计算文本:
cpp
复制代码
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)
}
}
}
5、LiveData KTX
使用 LiveData 时,您可能需要异步计算 值。例如,您可能需要检索用户的偏好设置并将其传送给界面。在这些情况下,LiveData KTX 可提供一个 liveData 构建器函数,该函数会调用 suspend 函数,并将结果作为 LiveData 对象传送。
要使用此模块,需在应用的 build.gradle 文件中添加相应的依赖项 。
cpp
复制代码
dependencies {
implementation("androidx.lifecycle:lifecycle-livedata-ktx:2.6.2")
}
可以使用 liveData 构建器 函数异步调用 loadUser(),然后使用 emit() 来发出结果:
cpp
复制代码
val user: LiveData<User> = liveData {
val data = database.loadUser() // loadUser is a suspend function.
emit(data)
}
6、Navigation KTX
Navigation 库的每个组件都有自己的 KTX 版本,用于调整 API 以使其更简洁且更符合 Kotlin 的语言习惯。
要使用此模块,需在应用的 build.gradle 文件中添加相应的依赖项 。
cpp
复制代码
dependencies {
implementation("androidx.navigation:navigation-runtime-ktx:2.7.5")
implementation("androidx.navigation:navigation-fragment-ktx:2.7.5")
implementation("androidx.navigation:navigation-ui-ktx:2.7.5")
}
可以使用扩展函数和属性委托来访问目标参数并导航到目标:
cpp
复制代码
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)
}
}
...
}
7、Palette KTX
Palette KTX 模块为使用调色板提供惯用的 Kotlin 支持。
要使用此模块,需在应用的 build.gradle 文件中添加相应的依赖项 。
cpp
复制代码
dependencies {
implementation("androidx.palette:palette-ktx:1.0.0")
}
使用 Palette 实例时,可以使用 get 运算符 ([ ]) 来检索给定 target 的 selected 色样:
cpp
复制代码
val palette = Palette.from(bitmap).generate()
val swatch = palette[target]
8、Reactive Streams KTX
利用 Reactive Streams KTX 模块可根据 ReactiveStreams 发布程序来创建可监测的 LiveData 流。
要使用此模块,需在应用的 build.gradle 文件中添加相应的依赖项 。
cpp
复制代码
dependencies {
implementation("androidx.lifecycle:lifecycle-reactivestreams-ktx:2.6.2")
}
假设一个数据库只有很少的用户。在应用中,将该数据库加载到内存中,然后在界面中显示用户数据。为此,可以使用 RxJava、Room Jetpack 组件以 Flowable 的形式检索用户列表。在这种情况下,还必须在 Fragment 或 Activity 的整个生命周期内管理 Rx 发布程序订阅。
不过,借助 LiveDataReactiveStreams,既可以利用 RxJava 及其丰富的运算符和工作安排功能,又可以享受 LiveData 的简便性:
cpp
复制代码
val fun getUsersLiveData() : LiveData<List<User>> {
val users: Flowable<List<User>> = dao.findUsers()
return LiveDataReactiveStreams.fromPublisher(users)
}
9、Room KTX
Room 扩展程序增加了对数据库事务的协程支持。
要使用此模块,需在应用的 build.gradle 文件中添加相应的依赖项 。
cpp
复制代码
dependencies {
implementation("androidx.room:room-ktx:2.7.1")
}
Room 使用协程的示例:第一个示例使用 suspend 函数返回 User 对象列表,而第二个示例利用 Kotlin 的 Flow 异步返回 User 列表。注意,使用 Flow 时,您还会收到有关您正在查询的表中任何更改的通知。
cpp
复制代码
@Query("SELECT * FROM Users")
suspend fun getUsers(): List<User>
@Query("SELECT * FROM Users")
fun getUsers(): Flow<List<User>>
10、SQLite KTX
SQLite 扩展程序将与 SQL 相关的代码封装在事务中,从而避免编写大量样板代码。
要使用此模块,需在应用的 build.gradle 文件中添加相应的依赖项 。
cpp
复制代码
dependencies {
implementation("androidx.sqlite:sqlite-ktx:2.5.1")
}
11、ViewModel KTX
ViewModel KTX 库提供了一个 viewModelScope() 函数,可让您更轻松地从 ViewModel 启动协程。CoroutineScope 绑定至 Dispatchers.Main,并且会在清除 ViewModel 后自动取消。您可以使用 viewModelScope(),而无需为每个 ViewModel 创建一个新范围。
要使用此模块,需在应用的 build.gradle 文件中添加相应的依赖项 。
cpp
复制代码
dependencies {
implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.2")
}
以下 viewModelScope() 函数会启动一个协程,用于在后台线程中发出网络请求。
cpp
复制代码
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()
}
12、WorkManager KTX
WorkManager KTX 为协程提供一流的支持。
要使用此模块,需在应用的 build.gradle 文件中添加相应的依赖项 。
kotlin
复制代码
dependencies {
implementation "androidx.work:work-runtime-ktx:2.9.0"
}
如果要构建一个简单的 CoroutineWorker 以执行某些网络操作,则需要执行以下操作:
kotlin
复制代码
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()
}
}
三、其他 KTX 模块
1、Firebase KTX
部分适用于 Android 的 Firebase SDK 具有 Kotlin 扩展库,可让您在应用中使用 Firebase 时编写惯用 Kotlin 代码。
有一些 KTX 扩展可用于 Google Maps Platform Android SDK,借助这些 KTX 扩展,您能够利用多种 Kotlin 语言功能(例如扩展函数、命名参数和默认参数),解构声明和协程。
3、Play Core KTX
Play Core KTX 通过向 Play Core 库中的 SplitInstallManager 和 AppUpdateManager 添加扩展函数,针对单发请求和用于监控状态更新的 Flow 添加了对 Kotlin 协程的支持。
要使用此模块,需在应用的 build.gradle 文件中添加相应的依赖项 。
kotlin
复制代码
dependencies {
implementation "com.google.android.play:core-ktx:1.8.1"
}
kotlin
复制代码
// 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()
}
}