在 Kotlin 中使用 Android 的 Java API 时,您会迅速意识到这样的作法失去了 Kotlin 语言简单有趣的特色。与其您亲自去编写这些 API 的 wrapper 和扩展函数,不如了解一下 Jetpack KTX 库。目前为止,已有超过 20 个库拥有对应的 KTX 版本,这些 KTX 库实现了经常使用的 Java 版本 API 的功能,包括 Android 平台 API、ViewModels、SQLite,甚至还有 Play Core。本文会介绍目前可用的 KTX API 并深刻其中去分析它们是如何实现的。java
若是您比较喜欢观看视频,能够 点击这里。android
为了提升 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 软件包app
要使用 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 中的自动完成功能找到它们。ide
其余功能,像 Color 类上能够使用的 解构 和 操做符重载 功能,能够访问 KTX 扩展程序列表 查看目前是否能够使用。函数
core-ktx
为来自 Android 平台的 API 提供了经常使用的 Kotlin 功能。this
例如,您正在使用 SharedPreferences
,当您想去更新一个值,不须要像使用 Java 同样执行 3 个调用,您只须要执行一个调用便可:google
/* 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()
函数会将数据修改异步写入磁盘。3d
// 来源 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 使用,这里我会快速介绍一下目前我使用的比较频繁的扩展。
不少 LiveData 的功能都是做为扩展函数实现的,好比:
例如,使用 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 予以支持。
要构造一个 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 经过它们各自对应的 -ktx 软件包提供了对协程的支持。咱们认为有必要更加深刻地介绍这部份内容,请继续关注相应的 "Modern Android Development 技巧" (简称为 "MAD Skills") 系列文章。
不单单是 AndroidX,其余一些模块也提供了对 KTX 的支持:
一旦您开始使用 -ktx
扩展,您的代码将会从简洁、易读和 Kotlin 习惯用语的特性中受益。敬请期待更多方法,并将 Kotlin 和 Jetpack 的优点应用于您的应用中。