Android KTX Część stanowiąca część Androida Jetpack.

KTX na Androidzie to zestaw rozszerzeń Kotlin, które są dołączone do Jetpacka i innych bibliotek Androida. Rozszerzenia KTX zapewniają zwięzłe, idiomatyczne interfejsy API Kotlin dla Jetpacka, platformy Android i innych interfejsów API. Te rozszerzenia wykorzystują kilka funkcji języka Kotlin, między innymi:

  • Funkcje rozszerzeń
  • Właściwości rozszerzenia
  • Lambda
  • Parametry nazwane
  • Domyślne wartości parametrów
  • Kortyny

Na przykład w przypadku korzystania z SharedPreferences przed wprowadzeniem zmian w danych dotyczących preferencji musisz utworzyć edytor. 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

W tym przypadku idealnie nadają się lambda Kotlin. Pozwalają one przyjąć bardziej zwięzłe podejście przez przekazanie bloku kodu do wykonania po utworzeniu edytora, zezwolenie na wykonanie kodu i zezwolenie interfejsowi API SharedPreferences na atomowe stosowanie zmian.

Oto przykład jednej z funkcji Android KTX Core (SharedPreferences.edit), która dodaje funkcję edycji do elementu SharedPreferences. Pierwszym argumentem tej funkcji jest opcjonalna flaga boolean, która wskazuje, czy zmiany mają zostać zatwierdzone, czy zastosowane. Otrzymuje też działanie do wykonania w edytorze SharedPreferences w postaci 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) }

Element wywołujący może wybrać, czy chce zatwierdzić zmiany, czy je zastosować. Lambda action jest samą anonimową funkcją rozszerzenia w SharedPreferences.Editor, która zwraca wartość Unit, jak wskazuje jej podpis. Dzięki temu możesz wykonywać pracę bezpośrednio w panelu SharedPreferences.Editor.

Podpis SharedPreferences.edit() zawiera słowo kluczowe inline. To słowo kluczowe informuje kompilator Kotlin, że powinien kopiować i wklejać (lub wbudować) skompilowany kod bajtowy funkcji za każdym razem, gdy jest używana. Pozwala to uniknąć konieczności tworzenia instancji nowej klasy dla każdego elementu action przy każdym wywołaniu tej funkcji.

Ten wzorzec przekazywania kodu za pomocą funkcji lambda, stosowanie rozsądnych wartości domyślnych, które można zastąpić, i dodawanie tych zachowań do istniejących interfejsów API za pomocą funkcji rozszerzeń inline jest typowym z ulepszeń zapewnianych przez bibliotekę KTX Androida.

Użyj KTX Androida w projekcie

Aby zacząć korzystać z KTX Androida, dodaj tę zależność do pliku build.gradle w Twoim projekcie:

Odlotowy

repositories {
    google()
}

Kotlin

repositories {
    google()
}

Moduły AndroidX

KTX Androida jest podzielony na moduły, z których każdy zawiera co najmniej 1 pakiet.

W pliku build.gradle aplikacji musisz umieścić zależność każdego artefaktu modułu. Pamiętaj, aby dołączyć do artefaktu numer wersji. Najnowsze numery wersji znajdziesz w odpowiednich sekcjach tego tematu.

KTX na Androidzie zawiera moduł jednordzeniowy, który zapewnia rozszerzenia Kotlin dla typowych interfejsów API platformy oraz kilka rozszerzeń specyficznych dla domeny.

Z wyjątkiem modułu głównego wszystkie artefakty modułu KTX zastępują bazową zależność Javy w pliku build.gradle. Zależność androidx.fragment:fragment możesz na przykład zastąpić wartoś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 zawiera rozszerzenia popularnych bibliotek, które są częścią platformy Androida. Te biblioteki nie mają zależności opartych na Javie, które trzeba dodać do build.gradle.

Aby uwzględnić ten moduł, dodaj następującą treść do pliku build.gradle aplikacji:

Odlotowy

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

Kotlin

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

Oto lista pakietów, które znajdują się w module Core KTX:

Kolekcja KTX

Rozszerzenia kolekcji zawierają przydatne funkcje umożliwiające pracę z bibliotekami zbierającymi efektywne pamięć Androida, takimi jak ArrayMap, LongSparseArray czy LruCache.

Aby korzystać z tego modułu, dodaj do pliku build.gradle swojej aplikacji:

Odlotowy

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

Kotlin

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

Rozszerzenia kolekcji wykorzystują przeciążenie operatora Kotlin, aby uprościć np. łączenie zbiorów, 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 następującą treść do pliku build.gradle aplikacji:

Odlotowy

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

Kotlin

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

Dzięki modułowi KTX fragmentu kodu możesz uprościć transakcje fragmentowe za pomocą lambda, np.:

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

Możesz też powiązać obiekt ViewModel w jednym wierszu, używając przedstawicieli 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>()

Cykl życia KTX

Cykl życia KTX definiuje LifecycleScope dla każdego obiektu Lifecycle. Każda współpraca uruchomiona w tym zakresie zostanie anulowana po zniszczeniu Lifecycle. 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 następującą treść do pliku build.gradle aplikacji:

Odlotowy

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

Kotlin

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

Ten przykład pokazuje, jak za pomocą lifecycleOwner.lifecycleScope asynchronicznie tworzyć wstępnie obliczony tekst:

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 swoim interfejsie. W takich przypadkach LiveData KTX udostępnia funkcję kreatora liveData, która wywołuje funkcję suspend i wyświetla wynik jako obiekt LiveData.

Aby uwzględnić ten moduł, dodaj następującą treść do pliku build.gradle aplikacji:

Odlotowy

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

Kotlin

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

W poniższym przykładzie loadUser() to funkcja zawieszania zadeklarowana w innym miejscu. Za pomocą funkcji konstruktora liveData możesz asynchronicznie wywoływać metodę loadUser(), a potem generować wynik za pomocą metody emit():

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 na temat używania współprogramów Kotlin z komponentami architektury.

Każdy komponent biblioteki nawigacji ma własną wersję KTX, która dostosowuje interfejs API, aby był bardziej zwięzły i kotlin-idiomatyczny.

Aby uwzględnić te moduły, dodaj te elementy do pliku build.gradle aplikacji:

Odlotowy

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

Kotlin

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

Za pomocą funkcji rozszerzeń i przekazywania właściwości możesz uzyskiwać dostęp do argumentów miejsc docelowych i przechodzić do miejsc docelowych, jak pokazano 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)
            }
     }
     ...

}

Paleta KTX

Moduł Palette KTX zapewnia idiomatyczną obsługę platformy Kotlin w zakresie pracy z paletami kolorów.

Aby korzystać z tego modułu, dodaj do pliku build.gradle swojej aplikacji:

Odlotowy

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 za pomocą operatora get ([ ]):

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

Reaktywne strumienie KTX

Moduł KTX strumieni reaktywnych umożliwia utworzenie obserwowanego strumienia LiveData od wydawcy ReactiveStreams.

Aby uwzględnić ten moduł, dodaj następującą treść do pliku build.gradle aplikacji:

Odlotowy

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

Kotlin

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

Załóżmy na przykład, że tworzysz bazę danych z niewielką listą użytkowników. W aplikacji wczytujesz bazę danych do pamięci, a potem wyświetlasz dane użytkownika w interfejsie. Możesz do tego użyć RxJava. Komponent Jetpack Room może pobierać listę użytkowników w postaci Flowable. W takiej sytuacji musisz też zarządzać subskrypcją wydawcy Rx przez cały okres aktywności fragmentu lub aktywności.

Dzięki LiveDataReactiveStreams możesz jednak korzystać z funkcji RxJava, jej bogatego zestawu operatorów i harmonogramu pracy, a także z łatwością funkcji LiveData, jak pokazano 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 dotyczące pokoi dodają obsługę transakcji do bazy danych.

Aby korzystać z tego modułu, dodaj do pliku build.gradle swojej aplikacji:

Odlotowy

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

Kotlin

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

Oto kilka przykładów sytuacji, w których funkcja Room używa teraz współprogramów. W pierwszym przykładzie użyto funkcji suspend do zwrócenia listy obiektów User, a w drugim funkcji Flow Kotlina do asynchronicznego zwracania listy User. Pamiętaj, że podczas korzystania z tabeli Flow będziesz też otrzymywać powiadomienia o wszelkich zmianach w tabelach, których dotyczy zapytanie.

@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 transakcjach, eliminując mnogość kodu.

Aby korzystać z tego modułu, dodaj do pliku build.gradle swojej aplikacji:

Odlotowy

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

Kotlin

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

Oto przykład użycia rozszerzenia transaction do wykonania transakcji w bazie danych:

db.transaction {
    // insert data
}

ViewModel KTX

Biblioteka KTX ViewModel udostępnia funkcję viewModelScope(), która ułatwia uruchamianie korekty z ViewModel. CoroutineScope jest powiązany z Dispatchers.Main i jest automatycznie anulowany po wyczyszczeniu ViewModel. Możesz użyć właściwości viewModelScope(), zamiast tworzyć nowy zakres dla każdej ViewModel.

Aby uwzględnić ten moduł, dodaj następującą treść do pliku build.gradle aplikacji:

Odlotowy

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

Kotlin

dependencies {
    implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.7.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 odpowiadające jej 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 pomoc w zakresie współprogramów.

Aby uwzględnić ten moduł, dodaj następującą treść do pliku build.gradle aplikacji:

Odlotowy

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

Kotlin

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

Zamiast rozszerzać zakres Worker, możesz teraz rozszerzyć rozszerzenie CoroutineWorker, który ma nieco inny interfejs API. Jeśli na przykład chcesz utworzyć prostą CoroutineWorker do wykonywania niektórych 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 korzystaniu z CoroutineWorker znajdziesz w artykule o wątkach w CoroutineWorker.

WorkManager KTX dodaje też funkcje rozszerzenia do Operations i ListenableFutures, aby zawiesić bieżącą współpracę.

Oto przykład, który powoduje zawieszenie działania Operation zwracanego przez metodę 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ż dołączyć dodatkowe moduły KTX, które istnieją poza AndroidemX.

KTX Firebase

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 tematach:

Google Maps Platform KTX

W pakietach SDK Google Maps Platform na Androida dostępne są rozszerzenia KTX, które pozwalają korzystać z kilku funkcji języka Kotlin, takich jak funkcje rozszerzeń, parametry nazwane i argumenty domyślne, deklaracje niszczycielskie oraz współprogramy. Więcej informacji można znaleźć w następujących tematach:

Zagraj w Core KTX

Play Core KTX dodaje obsługę współprogramów Kotlin w przypadku żądań typu „one-shot” oraz przepływa do monitorowania aktualizacji stanu – dodaliśmy funkcje rozszerzeń do SplitInstallManager i AppUpdateManager w bibliotece podstawowej Play.

Aby uwzględnić ten moduł, dodaj następującą treść do pliku build.gradle aplikacji:

Odlotowy

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 monitorowania stanu 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()
    }
}

Więcej informacji

Aby dowiedzieć się więcej o KTX na Androidzie, obejrzyj film o DevBytes.

Aby zgłosić problem lub zaproponować nową funkcję, skorzystaj z narzędzia Android KTX do śledzenia problemów.