Android KTX   Входит в Android Jetpack.

Android KTX – это набор расширений Kotlin, которые входят в состав Android Jetpack и других библиотек Android. Расширения KTX позволяют создавать лаконичный и идиоматичный код Kotlin для Jetpack, платформы Android и других API. Для этого в расширениях используются следующие функции языка Kotlin:

  • Функции расширений
  • Свойства расширения
  • Лямбда-функции
  • Именованные параметры
  • Значения параметров по умолчанию
  • Сопрограммы

Например, при работе с SharedPreferences необходимо создать редактор, прежде чем вы сможете вносить изменения в данные настроек. После внесения изменений их необходимо применить или зафиксировать, как показано в примере ниже.

sharedPreferences
        .edit()  // create an Editor
        .putBoolean("key", value)
        .apply() // write to disk asynchronously

Лямбда-выражения Kotlin идеально подходят для этого случая. Они позволяют использовать более лаконичный подход, передавая блок кода для выполнения после создания редактора, позволяя коду выполняться, а затем позволяя SharedPreferences API применять изменения атомарно.

Вот пример одной из функций Android KTX Core – SharedPreferences.edit, которая добавляет функцию редактирования в SharedPreferences. В качестве первого аргумента эта функция принимает необязательный флаг boolean, который указывает, нужно ли зафиксировать или применить изменения. Он также получает действие, которое нужно выполнить в редакторе SharedPreferences, в виде лямбда-выражения.

// SharedPreferences.edit extension function signature from Android KTX - Core
// inline fun SharedPreferences.edit(
//         commit: Boolean = false,
//         action: SharedPreferences.Editor.() -> Unit)

// Commit a new value asynchronously
sharedPreferences.edit { putBoolean("key", value) }

// Commit a new value synchronously
sharedPreferences.edit(commit = true) { putBoolean("key", value) }

Вызывающий абонент может выбрать, зафиксировать или применить изменения. Лямбда-выражение action – это анонимная функция расширения для SharedPreferences.Editor, которая возвращает Unit, как указано в ее сигнатуре. Поэтому внутри блока вы можете выполнять работу непосредственно над SharedPreferences.Editor.

Наконец, сигнатура SharedPreferences.edit() содержит ключевое слово inline. Это ключевое слово сообщает компилятору Kotlin, что он должен копировать и вставлять (или встраивать) скомпилированный байт-код для функции каждый раз, когда она используется. Это позволяет избежать создания нового класса для каждого объекта action при каждом вызове функции.

Такой шаблон передачи кода с помощью лямбда-выражений, применения разумных значений по умолчанию, которые можно переопределить, и добавления этих поведений в существующие API с помощью функций расширения inline типичен для улучшений, предоставляемых библиотекой Android KTX.

Как использовать Android KTX в проекте

Чтобы начать работу с Android KTX, добавьте в файл build.gradle проекта следующую зависимость:

Яркий

repositories {
    google()
}

Kotlin

repositories {
    google()
}

Модули AndroidX

Android KTX состоит из модулей, каждый из которых содержит один или несколько пакетов.

В файл build.gradle приложения необходимо добавить зависимость для каждого артефакта модуля. Не забудьте добавить номер версии к артефакту. Номера последних версий можно найти в разделе, посвященном каждому артефакту.

Android KTX содержит один основной модуль, который предоставляет расширения Kotlin для распространенных API фреймворка и несколько расширений для конкретных доменов.

За исключением основного модуля, все артефакты модуля KTX заменяют базовую зависимость Java в файле build.gradle. Например, вы можете заменить зависимость androidx.fragment:fragment на androidx.fragment:fragment-ktx. Такой синтаксис упрощает управление версиями и не требует дополнительных объявлений зависимостей.

Core KTX

Модуль Core KTX содержит расширения для стандартных библиотек, которые входят в состав фреймворка Android. У этих библиотек нет зависимостей на основе Java, которые нужно добавлять в файл build.gradle.

Чтобы включить этот модуль, добавьте в файл build.gradle своего приложения следующий код:

Классный

dependencies {
    implementation "androidx.core:core-ktx:1.19.1"
}

Котлин

dependencies {
    implementation("androidx.core:core-ktx:1.19.1")
}

Ниже приведен список пакетов, содержащихся в модуле Core KTX:

Collection KTX

Расширения Collection содержат служебные функции для работы с библиотеками коллекций Android, которые эффективно используют память, включая ArrayMap, LongSparseArray, LruCache и другие.

Чтобы использовать этот модуль, добавьте в файл build.gradle приложения следующий код:

классный

dependencies {
    implementation "androidx.collection:collection-ktx:1.6.0"
}

Котлин

dependencies {
    implementation("androidx.collection:collection-ktx:1.6.0")
}

Расширения коллекций используют перегрузку операторов Kotlin, чтобы упростить такие операции, как объединение коллекций, как показано в следующем примере:

// Combine 2 ArraySets into 1.
val combinedArraySet = arraySetOf(1, 2, 3) + arraySetOf(4, 5, 6)

// Combine with numbers to create a new sets.
val newArraySet = combinedArraySet + 7 + 8

Fragment KTX

Модуль Fragment KTX предоставляет ряд расширений для упрощения API фрагментов.

Чтобы включить этот модуль, добавьте в файл build.gradle своего приложения следующий код:

классный

dependencies {
    implementation "androidx.fragment:fragment-ktx:1.9.1"
}

Котлин

dependencies {
    implementation("androidx.fragment:fragment-ktx:1.9.1")
}

С помощью модуля Fragment KTX можно упростить транзакции для работы с фрагментами, используя лямбда-выражения, например:

fragmentManager().commit {
   addToBackStack("...")
   setCustomAnimations(
           R.anim.enter_anim,
           R.anim.exit_anim)
   add(fragment, "...")
}

Вы также можете выполнить привязку к ViewModel в одной строке, используя делегаты свойств viewModels и activityViewModels:

// Get a reference to the ViewModel scoped to this Fragment
val viewModel by viewModels<MyViewModel>()

// Get a reference to the ViewModel scoped to its Activity
val viewModel by activityViewModels<MyViewModel>()

Lifecycle KTX

Lifecycle KTX определяет LifecycleScope для каждого объекта Lifecycle. Любая сопрограмма, запущенная в этой области, отменяется при уничтожении Lifecycle. Получить доступ к свойству CoroutineScope объекта Lifecycle можно с помощью свойств lifecycle.coroutineScope или lifecycleOwner.lifecycleScope.

Чтобы включить этот модуль, добавьте в файл build.gradle своего приложения следующий код:

Классный

dependencies {
    implementation "androidx.lifecycle:lifecycle-runtime-ktx:2.11.0"
}

Котлин

dependencies {
    implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.11.0")
}

В примере ниже показано, как использовать lifecycleOwner.lifecycleScope для асинхронного создания предварительно вычисленного текста.

class MyFragment: Fragment() {
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        viewLifecycleOwner.lifecycleScope.launch {
            val params = TextViewCompat.getTextMetricsParams(textView)
            val precomputedText = withContext(Dispatchers.Default) {
                PrecomputedTextCompat.create(longTextContent, params)
            }
            TextViewCompat.setPrecomputedText(textView, precomputedText)
        }
    }
}

LiveData KTX

При использовании LiveData может потребоваться асинхронный расчет значений. Например, вы можете получить настройки пользователя и применить их к интерфейсу. Для таких случаев LiveData KTX предоставляет функцию-конструктор liveData, которая вызывает функцию suspend и возвращает результат в виде объекта LiveData.

Чтобы включить этот модуль, добавьте в файл build.gradle своего приложения следующий код:

Классный

dependencies {
    implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.11.0"
}

Котлин

dependencies {
    implementation("androidx.lifecycle:lifecycle-livedata-ktx:2.11.0")
}

В примере ниже loadUser() – это функция приостановки, объявленная в другом месте. Вы можете использовать функцию-конструктор liveData, чтобы асинхронно вызвать loadUser(), а затем использовать emit(), чтобы выдать результат:

val user: LiveData<User> = liveData {
    val data = database.loadUser() // loadUser is a suspend function.
    emit(data)
}

Подробнее о том, как использовать сопрограммы с LiveData, рассказывается в статье Использование сопрограмм Kotlin с компонентами архитектуры.

У каждого компонента библиотеки Navigation есть собственная версия KTX, которая адаптирует API, чтобы сделать его более лаконичным и идиоматичным для Kotlin.

Чтобы включить эти модули, добавьте в файл build.gradle своего приложения следующий код:

Классный

dependencies {
    implementation "androidx.navigation:navigation-runtime-ktx:2.10.2"
    implementation "androidx.navigation:navigation-fragment-ktx:2.10.2"
    implementation "androidx.navigation:navigation-ui-ktx:2.10.2"
}

Котлин

dependencies {
    implementation("androidx.navigation:navigation-runtime-ktx:2.10.2")
    implementation("androidx.navigation:navigation-fragment-ktx:2.10.2")
    implementation("androidx.navigation:navigation-ui-ktx:2.10.2")
}

Используйте функции расширения и делегирование свойств, чтобы получить доступ к аргументам пункта назначения и перейти к нему, как показано в следующем примере:

class MyDestination : Fragment() {

    // Type-safe arguments are accessed from the bundle.
    val args by navArgs<MyDestinationArgs>()

    ...
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        view.findViewById<Button>(R.id.next)
            .setOnClickListener {
                // Fragment extension added to retrieve a NavController from
                // any destination.
                findNavController().navigate(R.id.action_to_next_destination)
            }
     }
     ...

}

Palette KTX

Модуль Palette KTX предлагает идиоматическую поддержку Kotlin для работы с цветовыми палитрами.

Чтобы использовать этот модуль, добавьте в файл build.gradle приложения следующий код:

классный

dependencies {
    implementation "androidx.palette:palette-ktx:1.0.0"
}

Котлин

dependencies {
    implementation("androidx.palette:palette-ktx:1.0.0")
}

Например, при работе с экземпляром Palette вы можете получить образец selected для заданного target с помощью оператора get ([ ]):

val palette = Palette.from(bitmap).generate()
val swatch = palette[target]

Reactive Streams KTX

Модуль Reactive Streams KTX позволяет создать наблюдаемый поток LiveData из издателя ReactiveStreams.

Чтобы включить этот модуль, добавьте в файл build.gradle своего приложения следующий код:

Классный

dependencies {
    implementation "androidx.lifecycle:lifecycle-reactivestreams-ktx:2.11.0"
}

Котлин

dependencies {
    implementation("androidx.lifecycle:lifecycle-reactivestreams-ktx:2.11.0")
}

В качестве примера рассмотрим базу данных с небольшим списком пользователей. В приложении вы загружаете базу данных в память, а затем отображаете пользовательские данные в пользовательском интерфейсе. Для этого можно использовать RxJava. Компонент Jetpack Room может получить список пользователей в виде Flowable. В этом случае вам также нужно управлять подпиской издателя Rx на протяжении всего жизненного цикла фрагмента или действия.

Однако с помощью LiveDataReactiveStreams вы можете использовать RxJava и его богатый набор операторов и возможностей планирования работы, а также простоту LiveData, как показано в следующем примере:

val fun getUsersLiveData() : LiveData<List<User>> {
    val users: Flowable<List<User>> = dao.findUsers()
    return LiveDataReactiveStreams.fromPublisher(users)
}

Room KTX

Расширения Room добавляют поддержку сопрограмм для транзакций базы данных.

Чтобы использовать этот модуль, добавьте в файл build.gradle приложения следующий код:

Круто

dependencies {
    implementation "androidx.room:room-ktx:2.8.5"
}

Котлин

dependencies {
    implementation("androidx.room:room-ktx:2.8.5")
}

Вот несколько примеров, где Room теперь использует сопрограммы. В первом примере используется функция suspend, которая возвращает список объектов User, а во втором – Flow Kotlin, которая асинхронно возвращает список User. Обратите внимание, что при использовании Flow вы также будете получать уведомления обо всех изменениях в таблицах, к которым вы отправляете запросы.

@Query("SELECT * FROM Users")
suspend fun getUsers(): List<User>

@Query("SELECT * FROM Users")
fun getUsers(): Flow<List<User>>

SQLite KTX

Расширения SQLite упаковывают код, связанный с SQL, в транзакции, устраняя большую часть шаблонного кода.

Чтобы использовать этот модуль, добавьте в файл build.gradle приложения следующий код:

Классный

dependencies {
    implementation "androidx.sqlite:sqlite-ktx:2.7.1"
}

Котлин

dependencies {
    implementation("androidx.sqlite:sqlite-ktx:2.7.1")
}

Ниже приведен пример использования расширения transaction для выполнения транзакции в базе данных.

db.transaction {
    // insert data
}

ViewModel KTX

Библиотека ViewModel KTX предоставляет функцию viewModelScope(), которая упрощает запуск сопрограмм из ViewModel. CoroutineScope привязан к Dispatchers.Main и автоматически отменяется при очистке ViewModel. Вы можете использовать viewModelScope() вместо того, чтобы создавать новую область действия для каждого ViewModel.

Чтобы включить этот модуль, добавьте в файл build.gradle своего приложения следующий код:

Классный

dependencies {
    implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.11.0"
}

Котлин

dependencies {
    implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.11.0")
}

Например, следующая функция viewModelScope() запускает сопрограмму, которая выполняет сетевой запрос в фоновом потоке. Библиотека выполняет все настройки и очистку области действия:

class MainViewModel : ViewModel() {
    // Make a network request without blocking the UI thread
    private fun makeNetworkRequest() {
        // launch a coroutine in viewModelScope
        viewModelScope.launch  {
            remoteApi.slowFetch()
            ...
        }
    }

    // No need to override onCleared()
}

WorkManager KTX

WorkManager KTX обеспечивает первоклассную поддержку сопрограмм.

Чтобы включить этот модуль, добавьте в файл build.gradle своего приложения следующий код:

Классный

dependencies {
    implementation "androidx.work:work-runtime-ktx:2.12.0"
}

Котлин

dependencies {
    implementation("androidx.work:work-runtime-ktx:2.12.0")
}

Вместо расширения Worker теперь можно расширять CoroutineWorker, у которого немного другой API. Например, если вы хотите создать простой класс CoroutineWorker для выполнения некоторых сетевых операций, вы можете сделать следующее:

class CoroutineDownloadWorker(context: Context, params: WorkerParameters)
        : CoroutineWorker(context, params) {

    override suspend fun doWork(): Result = coroutineScope {
        val jobs = (0 until 100).map {
            async {
                downloadSynchronously("https://www.google.com")
            }
        }

        // awaitAll will throw an exception if a download fails, which
        // CoroutineWorker will treat as a failure
        jobs.awaitAll()
        Result.success()
    }
}

Дополнительную информацию об использовании CoroutineWorker можно найти в статье Потоки в CoroutineWorker.

WorkManager KTX также добавляет функции расширения в Operations и ListenableFutures, чтобы приостановить текущую сопрограмму.

Вот пример, в котором приостанавливается Operation, возвращенный enqueue():

// Inside of a coroutine...

// Run async operation and suspend until completed.
WorkManager.getInstance()
        .beginWith(longWorkRequest)
        .enqueue().await()

// Resume after work completes...

Другие модули KTX

Вы также можете включить дополнительные модули KTX, которые существуют за пределами AndroidX.

Firebase KTX

Некоторые Firebase SDK для Android содержат библиотеки расширений Kotlin, которые позволяют писать идиоматический код Kotlin при использовании Firebase в приложении. Дополнительную информацию можно найти в следующих статьях:

KTX для платформы Google Карт

Для SDK платформы Google Карт для Android доступны расширения KTX, которые позволяют использовать различные функции Kotlin, например расширения, именованные параметры и стандартные аргументы, деструктуризацию и сопрограммы. Дополнительную информацию можно найти в следующих статьях:

Play Core KTX

Play Core KTX добавляет поддержку сопрограмм Kotlin для однократных запросов и Flow для отслеживания обновлений статуса, добавляя функции расширения в SplitInstallManager и AppUpdateManager в библиотеке Play Core.

Чтобы включить этот модуль, добавьте в файл build.gradle своего приложения следующий код:

Яркий

dependencies {
    implementation "com.google.android.play:core-ktx:1.8.1"
}

Kotlin

dependencies {
    implementation("com.google.android.play:core-ktx:1.8.1")
}

Пример Flow для отслеживания статуса:

// Inside of a coroutine...

// Request in-app update status updates.
manager.requestUpdateFlow().collect { updateResult ->
    when (updateResult) {
        is AppUpdateResult.Available -> TODO()
        is AppUpdateResult.InProgress -> TODO()
        is AppUpdateResult.Downloaded -> TODO()
        AppUpdateResult.NotAvailable -> TODO()
    }
}

Дополнительная информация

Чтобы узнать больше об Android KTX, посмотрите видео DevBytes.

Чтобы сообщить о проблеме или предложить функцию, используйте систему отслеживания ошибок Android KTX.