Привет, Хабр. В преддверии старта курсов "Android Developer. Basic" и "Android Developer. Professional" подготовили перевод материала.
Когда вы используете Android Java API в Kotlin, к вам достаточно быстро приходит понимание, что вам не хватает некоторых фич Kotlin, которые делают написание кода намного проще и приятнее. Вместо того, чтобы писать свои собственные обертки и функции расширения для этих API, я рекомендую вам обратить внимание на набор библиотек Jetpack KTX. В настоящее время более 20 библиотек имеют собственную KTX версию, создающую прекрасные идиоматические версии Java API, начиная от API платформы Android до ViewModels, SQLite и даже Play Core. В этой статье мы рассмотрим некоторые из доступных нам API и заглянем под капот, чтобы увидеть, как они были созданы.
Если вы предпочитаете чтению просмотр видео, вы можете ознакомиться с материалом этой статьи здесь:
Обнаруживаемость
Чтобы повысить обнаруживаемость функциональности ktx
, рекомендуется всегда импортировать артефакт -ktx
, если он доступен. Поскольку артефакт -ktx
транзитивно зависит от не-ktx версии, вам не нужно включать другой артефакт. Например, для viewmodel
у вас есть 2 артефакта: viewmodel
и viewmodel-ktx
. Артефакт -ktx
будет содержать расширения Kotlin:
// Java language implementation
implementation "androidx.lifecycle:lifecycle-viewmodel:$lifecycle_version"
// Kotlin implementation
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version"
Всегда импортируйте артефакт -ktx
Для расширений API платформы Android следует импортировать артефакт core-ktx
.
implementation "androidx.core:core-ktx:$corektx_version"
Большинство функций ktx
реализовано как функции расширения, поэтому вы сможете легко найти их с помощью автокомплита в Android Studio.
Другие функции, такие как деструктуризация и перегрузка операторов, доступные в таких классах, как Color, можно обнаружить в списке расширений KTX.
API платформы — core-ktx
core-ktx
обеспечивает идиоматическую функциональность Kotlin для API платформы Android.
Например, если вы работаете с SharedPreferences
, когда вам нужно обновить значение, вместо выполнения трех разных вызовов вы можете обойтись всего одним:
/* 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)
+ }
Под капотом метод edit ktx вызывает ту же функциональность, по умолчанию предоставляя лучшую альтернативу commit — apply()
. apply ()
, в отличие от commit()
, фиксирует изменения на диске асинхронно:
// From https://cs.android.com/androidx/platform/frameworks/support/+/androidx-master-dev: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()
}
}
SharedPreferences.kt на GitHub
В core-ktx
вы также можете найти более простой способ работы с часто используемыми листнерами платформы. Например, если вы хотите триггерить экшн по изменению текста в EditText
, вам придется реализовать все методы TextWatcher
, даже если вас интересует только onTextChanged()
. 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) }
Это дает несколько преимуществ: ваш код становится читабельнее, поскольку он лаконичнее, и вы получаете лучшие аннотации именования и nullability
.
Вы можете найти похожие API листнеров для AnimatorListener и TransitionListener.
Под капотом doOnTextChanged реализован как функция расширения TextView
— класса, который также имеет метод addTextChangedListener
. doOnTextChanged
создает пустые реализации для других функций TextWatcher
.
API Jetpack
Большинство доступных расширений предназначены для API Jetpack. Здесь я просто рассмотрю некоторые из тех, которыми я пользовался чаще всего.
LiveData
Львиная доля функциональности LiveData также реализовано в виде функций расширения: такие методы как map, switchMap или distinctUntilChanged (источник).
Например, использование map из liveData-ktx
избавляет нас от необходимости вызывать Transformations.map(liveata) { /* map function */ }
и позволяет нам напрямую вызывать liveData.map
более идиоматическим способом в духе Kotlin.
Когда вы наблюдаете за объектом LiveData
, вам необходимо реализовывать Observer. Но с использованием метода observe
из lifecycle-ktx
код становится намного проще. Убедитесь, что вы вызываете импорт androidx.lifecycle.observe
, если метод не найден.
/* Copyright 2020 Google LLC.
SPDX-License-Identifier: Apache-2.0 */
- wordViewModel.allWords.observe(
- this,
- Observer { words ->
- // Update the cached copy of the words in the adapter.
- words?.let { adapter.submitList(it) }
- }
- )
+ wordViewModel.allWords.observe(owner = this) { words ->
+ // Update the cached copy of the words in the adapter.
+ words.let { adapter.submitList(it) }
+ }
LiveData
идеально подходит для предоставления данных, которые будут использоваться пользовательским интерфейсом, поэтому для преобразования из Flow в LiveData
и из LiveData
в Flow
, артефакт lifecycle-livedata-ktx
предоставляет две удобных функций расширения: Flow.asLiveData() и LiveData.asFlow().
Activity / Fragment и ViewModel
Чтобы создать ViewModel
, вы должны расширить класс ViewModel и реализовать ViewModelProvider.Factory, если ваша ViewModel
имеет зависимости. Чтобы создать ее инстанс, используйте делегат viewModels (подробнее о делегатах вы можете почитать здесь): 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)
}
viewModels
доступен в артефакте -ktx activity
и fragment
.
При работе с корутинами вы столкнетесь с необходимостью запускать корутину в ViewModel
. Работа, выполняемая корутиной, должна быть отменена при уничтожении ViewModel
. Вместо реализации своего собственного CoroutineScope
, используйте viewModelScope. Отмена будет произведена автоматически в ViewModel.onCleared(). Вы можете узнайте больше о тонкостях viewModelScope
в этой статье.
Room и WorkManager
И Room, и WorkManager предлагают поддержку корутин через свои артефакты -ktx
. Поскольку мы считаем, что об этом стоит рассказать более подробно, следите за обновлениями статей MAD ??Skills, посвященных этим библиотекам!
Другие модули KTX
Артефакты AndroidX — не единственные, кто предоставляет KTX версии:
Firebase создала общие расширения Kotlin
В Play Core есть артефакт core-ktx, обеспечивающий поддержку корутин для мониторинга обновлений в приложении
Лаконичность, удобочитаемость и Kotlin-идиоматичность — это фичи, которые принесут пользу вашему коду, как только вы начнете использовать -ktx
расширения. Следите за новостями, чтобы узнать о других способах использовать Kotlin и Jetpack в своем приложении!
Узнать подробнее о курсах: "Android Developer. Basic" / "Android Developer. Professional".
Приглашаем также на открытые вебинары:
• «Крестики-нолики на минималках» — игра на Android менее чем за 2 часа.• «Рисуем свой график котировок в Android»:
- Рассмотрим основные инструменты для рисования
- Изучим возможности классов Canvas, Path, Paint
- Нарисуем кастомизируемый график котировок и добавим в него анимации