Android KTX   Należy do Android Jetpack.

Android KTX to zestaw rozszerzeń Kotlina, które są zawarte w Androidzie Jetpack i innych bibliotek Androida. Rozszerzenia KTX zapewniają zwięzły, idiomatyczny Kotlin do Jetpacka, platformy Android i innych interfejsów API. Aby to zrobić, te rozszerzenia korzystają z kilku funkcji języka Kotlin, takich jak:

  • Funkcje rozszerzeń
  • Właściwości rozszerzenia
  • Lambda
  • Parametry nazwane
  • Wartości domyślne parametrów
  • współprogramy

Na przykład, gdy pracujesz z SharedPreferences, musisz utworzyć edytor, zanim będzie można wprowadzić 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 doskonale nadają się do tego zastosowania. Umożliwiają one bardziej zwięzłe podejście, ponieważ po utworzeniu edytora przekazujesz blok kodu do wykonania, a potem pozwalasz mu się wykonać, a następnie pozwalasz interfejsowi SharedPreferences API na zastosowanie zmian w atomowy sposób.

Oto przykład jednej z funkcji Android KTX Core, SharedPreferences.edit, która dodaje do SharedPreferences funkcję edycji. Pierwszym argumentem tej funkcji jest opcjonalna flaga boolean, która wskazuje, czy należy zatwierdzić czy zastosować zmiany. Otrzymuje też działanie do wykonania na SharedPreferences editorze 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) }

Rozmówca może zdecydować, czy wprowadzić zmiany, czy je zastosować. Funkcja lambda action jest anonimową funkcją rozszerzenia funkcji SharedPreferences.Editor, która zwraca Unit, zgodnie z jej sygnaturą. Dlatego w ramach tego bloku możesz wykonywać zadania bezpośrednio na stronie SharedPreferences.Editor.

Na koniec podpis SharedPreferences.edit() zawiera słowo kluczowe inline. To słowo kluczowe informuje kompilator Kotlina, że za każdym razem, gdy funkcja zostanie użyta, powinien skopiować i wkleić (lub wstawić w kodzie źródłowym) skompilowany bajtkod funkcji. Dzięki temu nie trzeba tworzyć nowej klasy za każdym razem, gdy ta funkcja jest wywoływana.action

Ten wzór przekazywania kodu za pomocą funkcji lambda, stosowania sensownych wartości domyślnych, które można zastąpić, oraz dodawania tych zachowań do istniejących interfejsów API za pomocą funkcji rozszerzenia inlinejest typowy dla ulepszeń oferowanych przez bibliotekę KTX Androida.

Używanie Androida KTX w projekcie

Aby zacząć używać Androida KTX, dodaj do pliku build.gradle projektu tę zależność:

Groovy

repositories {
    google()
}

Kotlin

repositories {
    google()
}

Moduły AndroidX

KTX na Androida jest zorganizowany w 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 dodać numer wersji do artefaktu. Najnowsze numery wersji znajdziesz w odpowiednich sekcjach dotyczących poszczególnych artefaktów w tym temacie.

Android KTX zawiera moduł z jednym rdzeniami, który udostępnia rozszerzenia Kotlina dla interfejsów API frameworków i kilka rozszerzeń dla konkretnych dziedzin.

Z wyjątkiem modułu podstawowego wszystkie artefakty modułu KTX zastępują w pliku build.gradle podrzędne zależności Javy. 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ć wersjonowaniem i nie wymaga dodatkowych deklaracji zależności.

Core KTX

Moduł Core KTX udostępnia rozszerzenia dla wspólnych bibliotek, które są częścią platformy Android. Te biblioteki nie mają zależności opartych na Javie, które musisz dodać do pliku build.gradle.

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

Odlotowe

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

Kotlin

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

Oto lista pakietów zawartych w module KTX Core:

Kolekcja KTX

Rozszerzenia kolekcji zawierają funkcje pomocnicze do pracy z bibliotekami kolekcji Androida, które oszczędzają pamięć, m.in. ArrayMap, LongSparseArray, LruCache i inne.

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

Groovy

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

Kotlin

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

Rozszerzenia kolekcji korzystają z przeciążenia operatora w Kotlinie, aby uprościć takie operacje jak konkatenacja kolekcji, jak pokazano 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 udostępnia kilka rozszerzeń upraszczających interfejs Fragment API.

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

Odlotowe

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

Kotlin

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

Za pomocą modułu 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ż za pomocą delegowanych właściwości viewModelsactivityViewModels powiązać się z elementem ViewModel w jednym wierszu:

// 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

KTX cyklu życia definiuje LifecycleScope dla każdego obiektu Lifecycle. Każda pętla współbieżna uruchomiona w tym zakresie jest anulowana, gdy Lifecycle zostanie zniszczona. Do właściwości CoroutineScope elementu Lifecycle możesz uzyskać dostęp za pomocą właściwości lifecycle.coroutineScope lub lifecycleOwner.lifecycleScope.

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

Groovy

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

Kotlin

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

Ten przykład pokazuje, jak za pomocą funkcji lifecycleOwner.lifecycleScope asynchronicznie tworzyć obliczony wstępnie 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 obliczanie wartości asynchronicznie. Na przykład możesz pobrać ustawienia użytkownika i wyświetlić je w interfejsie użytkownika. W takich przypadkach biblioteka LiveData KTX udostępnia funkcję 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.8.7"
}

Kotlin

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

W tym przykładzie loadUser() to funkcja zawieszania zadeklarowana gdzie indziej. Możesz użyć funkcji kreatora liveData, aby wywołać funkcję loadUser() asynchronicznie, a potem użyć funkcji emit(), aby wygenerować wynik:

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

Więcej informacji o używaniu coroutines w komponencie LiveData znajdziesz w artykule Używanie coroutines w komponentach Architecture.

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

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

Odlotowe

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

Kotlin

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

Aby uzyskać dostęp do argumentów miejsca docelowego i jego lokalizacji, 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 idiomatyczne wsparcie Kotlina do pracy z paletami kolorów.

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

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 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 tworzenie obserwowalnych strumieni LiveData z poziomu wydawcy ReactiveStreams.

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

Groovy

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

Kotlin

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

Załóżmy na przykład, że masz bazę danych z małą listą użytkowników. W aplikacji wczytujesz bazę danych do pamięci, a potem wyświetlasz dane użytkownika w interfejsie. Aby to zrobić, możesz użyć RxJava. Komponent Jetpacka Room może pobierać listę użytkowników jako Flowable. W takim przypadku musisz też zarządzać subskrypcją wydawcy Rx przez cały czas trwania fragmentu lub aktywności.

Dzięki LiveDataReactiveStreams możesz jednak korzystać z RxJava i bogatego zestawu operatorów oraz możliwości planowania pracy, a zarazem korzystać z prostoty LiveData, jak pokazano w tym przykładzie:

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

Room KTX

Rozszerzenia pokoju umożliwiają obsługę coroutines w przypadku transakcji bazy danych.

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

Odlotowe

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

Kotlin

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

Oto kilka przykładów, w których Room używa coroutines. Pierwszy przykład używa funkcji suspend do zwracania listy obiektów User, a drugi wykorzystuje funkcję Flow języka Kotlin do asynchronicznego zwracania listy User. Pamiętaj, że podczas korzystania z funkcji Flow otrzymujesz też 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 otaczają kod związany z SQL w transakcjach, eliminując w ten sposób wiele standardowych fragmentów kodu.

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

Odlotowe

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 bazy danych:

db.transaction {
    // insert data
}

ViewModel KTX

Biblioteka ViewModel KTX udostępnia funkcję viewModelScope(), która ułatwia uruchamianie współprocesów z poziomu ViewModel. Wyrażenie CoroutineScope jest powiązane z wyrażeniem Dispatchers.Main i zostaje automatycznie anulowane, gdy ViewModel zostanie wyczyszczone. Zamiast tworzyć nowy zakres dla każdego ViewModel, możesz użyć operatora viewModelScope().

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

Odlotowe

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

Kotlin

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

Na przykład funkcja viewModelScope() uruchamia coroutine, która wysyła żądanie sieciowe na wątku w tle. Biblioteka obsługuje wszystkie czynności związane z konfiguracją i odpowiednim oczyszczeniem 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 pierwszorzędne wsparcie dla coroutine.

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

Odlotowe

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

Kotlin

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

Zamiast rozszerzać interfejs Worker możesz teraz rozszerzać interfejs CoroutineWorker, który ma nieco inny interfejs API. Jeśli na przykład chcesz utworzyć prosty CoroutineWorker, który będzie wykonywał operacje sieciowe, 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 funkcji CoroutineWorker znajdziesz w artykule Pętle wątków w CoroutineWorker.

WorkManager KTX dodaje też funkcje rozszerzenia do funkcji OperationsListenableFutures, aby zawiesić bieżącą funkcję sterującą.

Oto przykład, który zawiesza działanie funkcji Operation zwracanej przez funkcję 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 mają biblioteki rozszerzeń Kotlina, które umożliwiają pisanie zwyczajnego kodu Kotlina podczas korzystania z Firebase w aplikacji. Więcej informacji znajdziesz w tych artykułach:

Google Maps Platform KTX

Dostępne są rozszerzenia KTX do pakietów SDK Google Maps Platform na Androida, które umożliwiają korzystanie z kilku funkcji języka Kotlin, takich jak funkcje rozszerzeń, parametry nazwane i domyślne, deklaracje destrukturyzowane i korowiny. Więcej informacji znajdziesz w tych artykułach:

Play Core KTX

Play Core KTX dodaje obsługę coroutine Kotlina do jednorazowych żądań i Flow do monitorowania aktualizacji stanu, dodając funkcje rozszerzeń do SplitInstallManagerAppUpdateManager w bibliotece Play Core.

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

Groovy

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 monitorującego stan:

// 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 Android KTX znajdziesz w filmie DevBytes.

Aby zgłosić problem lub zaproponować funkcję, skorzystaj z narzędzia do zgłaszania problemów z Androidem KTX.