在 Kotlin 中应用 Android 的 Java API 时,您会迅速意识到这样的做法失去了 Kotlin 语言简略乏味的特点。与其您亲自去编写这些 API 的 wrapper 和扩大函数,不如理解一下 Jetpack KTX 库。目前为止,已有超过 20 个库领有对应的 KTX 版本,这些 KTX 库实现了罕用的 Java 版本 API 的性能,包含 Android 平台 API、ViewModels、SQLite,甚至还有 Play Core。本文会介绍目前可用的 KTX API 并深刻其中去剖析它们是如何实现的。
如果您比拟喜爱观看视频,能够 点击这里。
可发现性
为了进步 ktx 性能的可发现性,作为最佳实际,当某个 ktx 库可用时,总是导入并应用它。因为 -ktx 传递依赖非 ktx 软件包,您不须要增加其余软件包。举个例子,应用 viewmodel 时,您能够看到两个软件包: viewmodel 和 viewmodel-ktx。-ktx 软件包会蕴含 Kotlin 的扩大:
// 获取最新 Lifecycle 库的版本信息
// https://developer.android.google.cn/jetpack/androidx/releases/lifecycle
def lifecycle_version = "2.3.1"
// Java 实现
implementation "androidx.lifecycle:lifecycle-viewmodel:$lifecycle_version"
// Kotlin 实现
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version"
始终导入 -ktx 软件包
要应用 Android 平台 API 的 Kotlin 扩大,导入 core-ktx 软件包即可。
// 获取最新 Core 库的版本信息
// https://developer.android.google.cn/jetpack/androidx/releases/core3def corektx_version = "1.3.2"
implementation "androidx.core:core-ktx:$corektx_version"
大部分 ktx 性能应用 扩大函数 实现的,您能够通过 Android Studio 中的主动实现性能找到它们。
其余性能,像 Color 类上能够应用的 解构 和 操作符重载 性能,能够拜访 KTX 扩大程序列表 查看目前是否能够应用。
平台 API — core-ktx
core-ktx
为来自 Android 平台的 API 提供了罕用的 Kotlin 性能。
例如,您正在应用 SharedPreferences
,当您想去更新一个值,不须要像应用 Java 一样执行 3 个调用,您只须要执行一个调用即可:
/* Copyright 2020 Google LLC.
SPDX-License-Identifier: Apache-2.0 */
- val editor = sharedPreferences.edit()
- editor.putBoolean(SHOW_DELETED_WORDS_KEY, enable)
- editor.apply()
+ sharedPreferences.edit {+ putBoolean(SHOW_DELETED_WORDS_KEY, enable)
+ }
在底层,ktx edit 办法和对应 Java 的 API 实现了雷同的性能,但 ktx edit 函数 提供了一个更好的默认的数据提交 commit 选项: apply()
。和 commit()
不同,apply()
函数会将数据批改异步写入磁盘。
// 起源 https://cs.android.com/androidx/platform/frameworks/support/+/androidx-main:core/core-ktx/src/main/java/androidx/core/content/SharedPreferences.kt;l=39?q=SharedPreferences.kt
public inline fun SharedPreferences.edit(
commit: Boolean = false,
action: SharedPreferences.Editor.() -> Unit) {val editor = edit()
action(editor)
if (commit) {editor.commit()
} else {editor.apply()
}
}
core-ktx
为解决平台罕用的监听器提供了更加简略的形式。例如,您须要在 EditText
的 text 发生变化时触发一个操作,如果应用 Java,即便您只须要 onTextChanged()
,您也必须实现 TextWatcher
接口中所有的函数。core-ktx
创立了 TextWatcher
中对应的办法: doOnTextChanged、doAfterTextChanged 以及 doBeforeTextChanged,在 Kotlin 中,您只须要实现您须要的接口:
/* Copyright 2020 Google LLC.
SPDX-License-Identifier: Apache-2.0 */
- editWordView.addTextChangedListener(object : TextWatcher {- override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {- handleTextChanged(s)
- }
-
- override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {-}
-
- override fun afterTextChanged(s: Editable) {-}
- })
+ editWordView.doOnTextChanged {text, start, count, after -> handleTextChanged(text) }
这样的变动会带来许多益处: 代码更加简洁,更好的命名和可空类型的正文,代码的可读性也失去进步。
AnimatorListener.addListener(kotlin.Function1,%20kotlin.Function1,%20kotlin.Function1,%20kotlin.Function1)) 和 TransitionListener.addListener(kotlin.Function1,%20kotlin.Function1,%20kotlin.Function1,%20kotlin.Function1,%20kotlin.Function1)) 也有相似的 API。
实现原理上,doOnTextChanged 是 TextView 的扩大函数 — addTextChangedListener 也是 TextView 的扩大函数,doOnTextChanged 为其余 TextWatcher 的函数创立了 空实现。
Jetpack API
可用的扩大次要提供给 Jetpack API 应用,这里我会疾速介绍一下目前我应用的比拟频繁的扩大。
LiveData
很多 LiveData 的性能都是作为扩大函数实现的,比方:
- map
- switchMap
- distinctUntilChanged
- distinctUntilChanged 源码
例如,应用 livedata-ktx
的 map 函数,咱们不须要调用 Transformations.map(livedata) {/*map 函数体 */}
,livedata-ktx
容许咱们通过 Kotlin 习用的形式间接调用 livedData.map
。
当您察看一个 LiveData
对象时,您必须实现 Observer 接口。然而应用 lifecycle-ktx
的 observe 函数后,代码会变得更加简洁。如果提醒 observe 办法找不到,请确认您曾经导入 androidx.lifecycle.observe
。
/* Copyright 2020 Google LLC.
SPDX-License-Identifier: Apache-2.0 */
- wordViewModel.allWords.observe(
- this,
- Observer { words ->
- // 更新 adapter 中缓存的 words 正本
- words?.let {adapter.submitList(it) }
- }
- )
+ wordViewModel.allWords.observe(owner = this) { words ->
+ // 更新 adapter 中缓存的 words 正本
+ words.let {adapter.submitList(it) }
+ }
LiveData 非常适合用于将数据裸露给 UI 应用,因而 lifecycle-livedata-ktx 软件包提供了两个简略的扩大函数: Flow.asLiveData()、LiveData.asFlow(),别离对 Flow 转换成 LiveData 以及将 LiveData 转换成 Flow 予以反对。
Activity / Fragment 和 ViewModel
要结构一个 ViewModel,须要扩大 ViewModel 类,如果 ViewModel 有其余依赖,还须要实现 ViewModelProvider.Factory 接口。要实例化 ViewModel.viewModels(kotlin.Function0)),能够应用 viewModels 委托 (详阅: Kotlin Vocabulary | Kotlin 委托代理): by ViewModels(factory)
:
/* Copyright 2020 Google LLC.
SPDX-License-Identifier: Apache-2.0 */
+ private val wordViewModel: WordViewModel by viewModels {+ WordViewModelFactory(repository)
+ }
override fun onCreate(savedInstanceState: Bundle?) {
…
- val viewModelFactory = WordViewModelFactory(repository)
- val viewModel = ViewModelProvider(this, viewModelFactory).get(WordViewModel::class.java)
}
Activity
和 Fragment
的 -ktx 软件包都提供了 viewModel
反对。
应用协程时,您可能会在 ViewModel 中启动一个协程。当 ViewModel 被销毁时,须要勾销协程工作的执行。应用 viewModelScope
后,您不须要实现 CoroutineScope
,协程工作的勾销会在 viewModel.onCleared()
函数中主动执行。浏览 相干文章 理解 viewModelScope
的前因后果。
Room 和 WorkManager
Room 和 WorkManager 通过它们各自对应的 -ktx 软件包提供了对协程的反对。咱们认为有必要更加深刻地介绍这部分内容,请持续关注相应的 “Modern Android Development 技巧 ” (简称为 “MAD Skills”) 系列文章。
其余 KTX 模块
不仅仅是 AndroidX,其余一些模块也提供了对 KTX 的反对:
- Firebase 创立了一些 通用 Kotlin 扩大;
- Google Maps 提供了 Maps 和 Places 的 ktx 库;
- Play Core 有 core-ktx 软件包,为监控利用内更新状态提供协程反对。
一旦您开始应用 -ktx
扩大,您的代码将会从简洁、易读和 Kotlin 习惯用语的个性中受害。敬请期待更多办法,并将 Kotlin 和 Jetpack 的劣势利用于您的利用中。