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

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

Ядро КТХ

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

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

классный

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

Котлин

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

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

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

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

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

классный

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

Котлин

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

Расширения коллекций используют преимущества перегрузки операторов 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.4"
}

Котлин

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

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

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

классный

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

Котлин

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

классный

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

Котлин

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

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

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

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

классный

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

Котлин

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

классный

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

Котлин

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

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

Groovy

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

Kotlin

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

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

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.6.2"
}

Kotlin

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

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

Котлин

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

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

Котлин

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

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

db.transaction {
    // insert data
}

Просмотр модели KTX

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

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

классный

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

Котлин

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

классный

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

Котлин

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

Например, следующая функция 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 обеспечивает первоклассную поддержку сопрограмм.

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

классный

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

Котлин

dependencies {
    implementation("androidx.work:work-runtime-ktx:2.9.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.

Огневая база КТХ

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

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

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

Играть в ядро ​​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 .