优先使用 KTX 库 | MAD Skills

在 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 扩展程序列表 查看目前是否能够使用。函数

平台 API — core-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 中对应的方法: doOnTextChangeddoAfterTextChanged 以及 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 的功能都是做为扩展函数实现的,好比:

例如,使用 livedata-ktxmap 函数,咱们不须要调用 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)
}

ActivityFragment 的 -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 提供了 MapsPlaces 的 ktx 库;
  • Play Core 有 core-ktx 软件包,为监控应用内更新状态提供协程支持。

一旦您开始使用 -ktx 扩展,您的代码将会从简洁、易读和 Kotlin 习惯用语的特性中受益。敬请期待更多方法,并将 Kotlin 和 Jetpack 的优点应用于您的应用中。

相关文章
相关标签/搜索