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 идеально подходят для этого случая. Они позволяют использовать более лаконичный подход: передать блок кода для выполнения после создания редактора, дождаться его выполнения, а затем позволить API SharedPreferences атомарно применить изменения.

Вот пример одной из функций 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()
}

Котлин

repositories {
    google()
}

Модули AndroidX

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

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

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

За исключением модуля core, все артефакты модулей 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.16.0"
}

Котлин

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

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

Коллекция КТХ

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

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

классный

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

Котлин

dependencies {
    implementation("androidx.collection:collection-ktx:1.5.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 предоставляет ряд расширений для упрощения API фрагментов.

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

классный

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

Котлин

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

С помощью модуля 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>()

Жизненный цикл KTX

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

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

Круто

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

Котлин

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

Круто

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

Котлин

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

В следующем примере показано, как использовать 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.9.1"
}

Котлин

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

Круто

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

Котлин

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

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

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

Дополнительную информацию об использовании сопрограмм с LiveData см. в разделе Использование сопрограмм Kotlin с компонентами архитектуры .

Каждый компонент библиотеки навигации имеет собственную версию KTX, которая адаптирует API, делая его более лаконичным и идиоматичным для Kotlin.

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

классный

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

Котлин

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

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

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 предлагает идиоматическую поддержку 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]

Реактивные потоки KTX

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

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

Groovy

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

Kotlin

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

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

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

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

Комната КТХ

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

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

классный

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

Котлин

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

Вот несколько примеров, где 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 вашего приложения:

Groovy

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

Kotlin

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

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

db.transaction {
    // insert data
}

ViewModel KTX

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

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

Groovy

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

Kotlin

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

Например, следующая функция 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.10.2"
}

Котлин

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

Вместо расширения 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 в вашем приложении. Подробнее см. в следующих разделах:

Платформа Google Карт KTX

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

Играть в Core KTX

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

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

Круто

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

Котлин

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 .