優先使用 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 的優點應用於您的應用中。

相關文章
相關標籤/搜索