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