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, 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 фреймворка, а также несколько расширений, специфичных для конкретных областей применения.

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

Котлин

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

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

Коллекция 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

Фрагмент KTX

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

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

классный

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

Котлин

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

С помощью модуля 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 для каждого объекта Lifecycle определяется область LifecycleScope . Любая сопрограмма, запущенная в этой области видимости, отменяется при уничтожении объекта Lifecycle . Доступ CoroutineScope объекта Lifecycle можно получить, используя свойства lifecycle.coroutineScope или lifecycleOwner.lifecycleScope .

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

Классный

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

Котлин

dependencies {
    implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.10.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.10.0"
}

Котлин

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

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

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

Для получения дополнительной информации об использовании корутин с LiveData см. раздел «Использование корутин Kotlin с компонентами Architecture» .

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

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

классный

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

Котлин

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

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

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)
            }
     }
     ...

}

Палитра 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]

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

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

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

Классный

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

Котлин

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

В качестве примера предположим, что у вас есть база данных с небольшим списком пользователей. В вашем приложении вы загружаете базу данных в память, а затем отображаете данные пользователей в пользовательском интерфейсе. Для этого вы можете использовать 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)
}

Комната KTX

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

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

Круто

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

Котлин

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

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

Котлин

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

Вот пример использования расширения 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.10.0"
}

Котлин

dependencies {
    implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.10.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.11.1"
}

Котлин

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

Вместо расширения 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

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

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

Для Android SDK платформы Google Maps доступны расширения 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"
}

Котлин

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 .