Android KTX Jest częścią Android Jetpack.
Android KTX to zestaw rozszerzeń Kotlin, które są dołączone do Androida Jetpack i innych bibliotek Androida. Rozszerzenia KTX zapewniają zwięzły, idiomatyczny kod Kotlin dla Jetpacka, platformy Androida i innych interfejsów API. W tym celu rozszerzenia te wykorzystują kilka funkcji języka Kotlin, w tym:
- Funkcje rozszerzeń
- Właściwości rozszerzenia
- Lambdy
- Nazwane parametry
- Wartości domyślne parametrów
- Korutyny
Na przykład podczas pracy z SharedPreferences musisz utworzyć edytor, zanim będzie można wprowadzać zmiany w danych preferencji. Po zakończeniu edycji musisz też zastosować lub zatwierdzić te zmiany, jak pokazano w tym przykładzie:
sharedPreferences
.edit() // create an Editor
.putBoolean("key", value)
.apply() // write to disk asynchronously
Funkcje lambda w Kotlinie idealnie nadają się do tego przypadku użycia. Pozwalają one na bardziej zwięzłe podejście, ponieważ przekazują blok kodu do wykonania po utworzeniu edytora, umożliwiają wykonanie kodu, a następnie pozwalają interfejsowi API SharedPreferences na zastosowanie zmian w sposób niepodzielny.
Oto przykład jednej z funkcji Android KTX Core:
SharedPreferences.edit,
która dodaje funkcję edycji do SharedPreferences. Ta funkcja przyjmuje opcjonalną flagę boolean jako pierwszy argument, który wskazuje, czy zatwierdzić, czy zastosować zmiany. Otrzymuje też działanie do wykonania w edytorze SharedPreferences w postaci funkcji lambda.
// 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) }
Osoba wywołująca może wybrać, czy chce zatwierdzić, czy zastosować zmiany. action
lambda jest anonimową funkcją rozszerzenia w SharedPreferences.Editor,
która zwraca Unit, jak wskazuje jej sygnatura. Dlatego w bloku
możesz wykonywać zadania bezpośrednio na
SharedPreferences.Editor.
Na koniec podpis SharedPreferences.edit() zawiera słowo kluczowe inline.
To słowo kluczowe informuje kompilator Kotlin, że powinien skopiować i wkleić (lub wstawić) skompilowany kod bajtowy funkcji za każdym razem, gdy jest ona używana.
Pozwala to uniknąć narzutu związanego z tworzeniem instancji nowej klasy dla każdego elementu action przy każdym wywołaniu tej funkcji.
Ten wzorzec przekazywania kodu za pomocą funkcji lambda, stosowania rozsądnych wartości domyślnych, które można zastąpić, i dodawania tych zachowań do istniejących interfejsów API za pomocą funkcji rozszerzeń inline jest typowy dla ulepszeń zapewnianych przez bibliotekę Android KTX.
Używanie Androida KTX w projekcie
Aby zacząć korzystać z Androida KTX, dodaj do pliku build.gradle projektu tę zależność:
Dynamiczny
repositories { google() }
Kotlin
repositories { google() }
Moduły AndroidX
Android KTX jest podzielony na moduły, z których każdy zawiera co najmniej 1 pakiet.
W pliku build.gradle aplikacji musisz uwzględnić zależność dla każdego artefaktu modułu. Pamiętaj, aby dołączyć do artefaktu numer wersji.
Numery najnowszych wersji znajdziesz w sekcji dotyczącej poszczególnych artefaktów w tym temacie.
Android KTX zawiera pojedynczy moduł podstawowy, który udostępnia rozszerzenia Kotlin dla popularnych interfejsów API platformy i kilka rozszerzeń dla konkretnych domen.
Z wyjątkiem modułu podstawowego wszystkie artefakty modułu KTX zastępują podstawową zależność Javy w pliku build.gradle. Możesz na przykład zastąpić zależność androidx.fragment:fragment zależnością androidx.fragment:fragment-ktx. Ta składnia pomaga lepiej zarządzać obsługą wersji i nie dodaje dodatkowych wymagań dotyczących deklaracji zależności.
Core KTX
Moduł Core KTX udostępnia rozszerzenia popularnych bibliotek, które są częścią platformy Androida. Te biblioteki nie mają zależności opartych na języku Java, które trzeba dodać do pliku build.gradle.
Aby uwzględnić ten moduł, dodaj do pliku build.gradle aplikacji te informacje:
Groovy
dependencies { implementation "androidx.core:core-ktx:1.19.1" }
Kotlin
dependencies { implementation("androidx.core:core-ktx:1.19.1") }
Oto lista pakietów zawartych w module Core KTX:
- androidx.core.animation
- androidx.core.content
- androidx.core.content.res
- androidx.core.database
- androidx.core.database.sqlite
- androidx.core.graphics
- androidx.core.graphics.drawable
- androidx.core.location
- androidx.core.net
- androidx.core.os
- androidx.core.text
- androidx.core.transition
- androidx.core.util
- androidx.core.view
- androidx.core.widget
Kolekcja KTX
Rozszerzenia kolekcji zawierają funkcje użytkowe do pracy z bibliotekami kolekcji Androida, które efektywnie wykorzystują pamięć, takimi jak ArrayMap, LongSparseArray, LruCache i inne.
Aby użyć tego modułu, dodaj do pliku build.gradle aplikacji:
Groovy
dependencies { implementation "androidx.collection:collection-ktx:1.6.0" }
Kotlin
dependencies { implementation("androidx.collection:collection-ktx:1.6.0") }
Rozszerzenia kolekcji wykorzystują przeciążanie operatorów w języku Kotlin, aby uprościć takie operacje jak konkatenacja kolekcji, jak w tym przykładzie:
// 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
Moduł Fragment KTX zawiera szereg rozszerzeń, które upraszczają interfejs API fragmentów.
Aby uwzględnić ten moduł, dodaj do pliku build.gradle aplikacji te informacje:
Odlotowe
dependencies { implementation "androidx.fragment:fragment-ktx:1.9.1" }
Kotlin
dependencies { implementation("androidx.fragment:fragment-ktx:1.9.1") }
Dzięki modułowi Fragment KTX możesz uprościć transakcje fragmentów za pomocą funkcji lambda, na przykład:
fragmentManager().commit {
addToBackStack("...")
setCustomAnimations(
R.anim.enter_anim,
R.anim.exit_anim)
add(fragment, "...")
}
Możesz też powiązać z ViewModel w jednym wierszu, używając delegatów właściwości viewModels i 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 definiuje LifecycleScope dla każdego obiektu Lifecycle. Wszystkie współprogramy uruchomione w tym zakresie są anulowane, gdy Lifecycle zostanie zniszczony. Dostęp do CoroutineScope elementu Lifecycle możesz uzyskać za pomocą właściwości lifecycle.coroutineScope lub lifecycleOwner.lifecycleScope.
Aby uwzględnić ten moduł, dodaj do pliku build.gradle aplikacji te informacje:
Groovy
dependencies { implementation "androidx.lifecycle:lifecycle-runtime-ktx:2.11.0" }
Kotlin
dependencies { implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.11.0") }
Poniższy przykład pokazuje, jak używać lifecycleOwner.lifecycleScope do asynchronicznego tworzenia wstępnie obliczonego tekstu:
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
Podczas korzystania z LiveData może być konieczne asynchroniczne obliczanie wartości. Możesz na przykład pobrać ustawienia użytkownika i wyświetlić je w interfejsie. W takich przypadkach LiveData KTX udostępnia funkcję kreatora liveData, która wywołuje funkcję suspend i zwraca wynik jako obiekt LiveData.
Aby uwzględnić ten moduł, dodaj do pliku build.gradle aplikacji te informacje:
Groovy
dependencies { implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.11.0" }
Kotlin
dependencies { implementation("androidx.lifecycle:lifecycle-livedata-ktx:2.11.0") }
W przykładzie poniżej loadUser() to funkcja zawieszenia zadeklarowana w innym miejscu.
Możesz użyć funkcji kreatora liveData, aby asynchronicznie wywołać loadUser(), a następnie użyć emit() do wygenerowania wyniku:
val user: LiveData<User> = liveData {
val data = database.loadUser() // loadUser is a suspend function.
emit(data)
}
Więcej informacji o używaniu współprogramów z LiveData znajdziesz w artykule Używanie współprogramów Kotlin z komponentami architektury.
Navigation KTX
Każdy komponent biblioteki nawigacji ma własną wersję KTX, która dostosowuje interfejs API, aby był bardziej zwięzły i idiomatyczny dla Kotlina.
Aby uwzględnić te moduły, dodaj do pliku build.gradle aplikacji te wiersze:
Groovy
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" }
Kotlin
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") }
Aby uzyskać dostęp do argumentów miejsca docelowego i przejść do miejsc docelowych, użyj funkcji rozszerzenia i delegowania właściwości, jak w tym przykładzie:
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
Moduł Palette KTX zapewnia idiomatyczną obsługę języka Kotlin podczas pracy z paletami kolorów.
Aby użyć tego modułu, dodaj do pliku build.gradle aplikacji:
Odlotowe
dependencies { implementation "androidx.palette:palette-ktx:1.0.0" }
Kotlin
dependencies { implementation("androidx.palette:palette-ktx:1.0.0") }
Na przykład podczas pracy z instancją Palette możesz pobrać próbkę selected dla danego elementu target, używając operatora get ([ ]):
val palette = Palette.from(bitmap).generate()
val swatch = palette[target]
Reactive Streams KTX
Moduł Reactive Streams KTX umożliwia utworzenie obserwowalnego strumienia LiveData z obiektu ReactiveStreams.
Aby uwzględnić ten moduł, dodaj do pliku build.gradle aplikacji te informacje:
Groovy
dependencies { implementation "androidx.lifecycle:lifecycle-reactivestreams-ktx:2.11.0" }
Kotlin
dependencies { implementation("androidx.lifecycle:lifecycle-reactivestreams-ktx:2.11.0") }
Załóżmy na przykład, że baza danych zawiera krótką listę użytkowników. W aplikacji wczytujesz bazę danych do pamięci, a następnie wyświetlasz dane użytkownika w interfejsie. Aby to osiągnąć, możesz użyć RxJava.
Komponent Jetpack Room może pobrać listę użytkowników jako Flowable. W takim przypadku musisz też zarządzać subskrypcją wydawcy Rx przez cały okres istnienia fragmentu lub aktywności.
Jednak dzięki LiveDataReactiveStreams możesz korzystać z RxJava i jej bogatego zestawu operatorów oraz funkcji planowania pracy, a jednocześnie pracować z prostotą LiveData, jak w tym przykładzie:
val fun getUsersLiveData() : LiveData<List<User>> {
val users: Flowable<List<User>> = dao.findUsers()
return LiveDataReactiveStreams.fromPublisher(users)
}
Pokój KTX
Rozszerzenia Room dodają obsługę współprogramów w transakcjach baz danych.
Aby użyć tego modułu, dodaj do pliku build.gradle aplikacji:
Groovy
dependencies { implementation "androidx.room:room-ktx:2.8.5" }
Kotlin
dependencies { implementation("androidx.room:room-ktx:2.8.5") }
Oto kilka przykładów, w których Room używa teraz współprogramów. W pierwszym przykładzie użyto funkcji suspend, aby zwrócić listę obiektów User, a w drugim – Flow w języku Kotlin, aby asynchronicznie zwrócić listę User. Pamiętaj, że gdy używasz Flow, otrzymujesz też powiadomienia o wszelkich zmianach w tabelach, do których wysyłasz zapytania.
@Query("SELECT * FROM Users")
suspend fun getUsers(): List<User>
@Query("SELECT * FROM Users")
fun getUsers(): Flow<List<User>>
SQLite KTX
Rozszerzenia SQLite opakowują kod związany z SQL w transakcje, eliminując wiele powtarzalnego kodu.
Aby użyć tego modułu, dodaj do pliku build.gradle aplikacji:
Groovy
dependencies { implementation "androidx.sqlite:sqlite-ktx:2.7.1" }
Kotlin
dependencies { implementation("androidx.sqlite:sqlite-ktx:2.7.1") }
Oto przykład użycia rozszerzenia transaction do wykonania transakcji w bazie danych:
db.transaction {
// insert data
}
ViewModel KTX
Biblioteka ViewModel KTX udostępnia funkcję viewModelScope(), która ułatwia uruchamianie współprogramów z ViewModel. CoroutineScope jest powiązany z Dispatchers.Main i jest automatycznie anulowany po wyczyszczeniu ViewModel. Zamiast tworzyć nowy zakres dla każdego elementu ViewModel, możesz użyć viewModelScope().
Aby uwzględnić ten moduł, dodaj do pliku build.gradle aplikacji te informacje:
Groovy
dependencies { implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.11.0" }
Kotlin
dependencies { implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.11.0") }
Na przykład ta funkcja viewModelScope() uruchamia współprogram, który wysyła żądanie sieciowe w wątku w tle. Biblioteka obsługuje całą konfigurację i odpowiednie czyszczenie zakresu:
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 zapewnia najwyższej klasy obsługę współprogramów.
Aby uwzględnić ten moduł, dodaj do pliku build.gradle aplikacji te informacje:
Dynamiczny
dependencies { implementation "androidx.work:work-runtime-ktx:2.12.0" }
Kotlin
dependencies { implementation("androidx.work:work-runtime-ktx:2.12.0") }
Zamiast rozszerzać Worker, możesz teraz rozszerzyć CoroutineWorker, który ma nieco inny interfejs API. Jeśli na przykład chcesz utworzyć prostą aplikację CoroutineWorker do wykonywania operacji sieciowych, możesz wykonać te czynności:
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()
}
}
Więcej informacji o używaniu CoroutineWorker znajdziesz w artykule Wątki w CoroutineWorker.
WorkManager KTX dodaje też funkcje rozszerzeń do Operations i ListenableFutures, aby zawiesić bieżący współprogram.
Oto przykład, który zawiesza Operation zwracany przez enqueue():
// Inside of a coroutine...
// Run async operation and suspend until completed.
WorkManager.getInstance()
.beginWith(longWorkRequest)
.enqueue().await()
// Resume after work completes...
Inne moduły KTX
Możesz też uwzględnić dodatkowe moduły KTX, które istnieją poza AndroidX.
Firebase KTX
Niektóre pakiety SDK Firebase na Androida zawierają biblioteki rozszerzeń Kotlin, które umożliwiają pisanie idiomatycznego kodu Kotlin podczas korzystania z Firebase w aplikacji. Więcej informacji znajdziesz w tych artykułach:
Google Maps Platform KTX
Dostępne są rozszerzenia KTX dla pakietów Android SDK Google Maps Platform, które umożliwiają korzystanie z kilku funkcji języka Kotlin, takich jak funkcje rozszerzeń, nazwane parametry i argumenty domyślne, deklaracje destrukturyzujące i współprogramy. Więcej informacji znajdziesz w tych artykułach:
Play Core KTX
Play Core KTX dodaje obsługę współprogramów Kotlin w przypadku żądań jednorazowych i Flow do monitorowania aktualizacji stanu przez dodanie funkcji rozszerzeń do SplitInstallManager i AppUpdateManager w bibliotece Play Core.
Aby uwzględnić ten moduł, dodaj do pliku build.gradle aplikacji te informacje:
Dynamiczny
dependencies { implementation "com.google.android.play:core-ktx:1.8.1" }
Kotlin
dependencies { implementation("com.google.android.play:core-ktx:1.8.1") }
Oto przykład Flow monitorowania stanu:
// 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()
}
}
Więcej informacji
Więcej informacji o Androidzie KTX znajdziesz w filmie DevBytes.
Aby zgłosić problem lub zaproponować funkcję, użyj narzędzia Issue Tracker Androida KTX.