Android KTX Część Android Jetpack.

Android KTX to zestaw rozszerzeń Kotlin, które są dołączane do Androida Jetpack i innych bibliotek Androida. Rozszerzenia KTX zapewniają zwięzłe, idiotyczne narzędzie Kotlin do Jetpacka, platformy Android i innych interfejsów API. Wykorzystują one do tego kilka funkcji w języku Kotlin, w tym:

  • Funkcje rozszerzeń
  • Właściwości rozszerzenia
  • Funkcje lambda
  • Nazwane parametry
  • Domyślne wartości parametru
  • Koutyny

Na przykład podczas pracy z SharedPreferences, zanim zmodyfikujesz dane preferencji, musisz utworzyć edytor. Po zakończeniu edycji musisz też zastosować lub zatwierdzić te zmiany, jak w tym przykładzie:

sharedPreferences
        .edit()  // create an Editor
        .putBoolean("key", value)
        .apply() // write to disk asynchronously

W tym przypadku idealnie sprawdzają się lambda Kotlin. Pozwalają one przyjąć bardziej zwięzłe podejście – po utworzeniu edytora przekazują blok kodu do wykonania, a następnie umożliwiają jego wykonanie, a interfejs API SharedPreferences umożliwia atomowe zastosowanie zmian.

Oto przykład jednej z funkcji SharedPreferences.edit w Android KTX Core, która dodaje funkcję edycji do SharedPreferences. Ta funkcja wykorzystuje opcjonalną flagę boolean jako pierwszy argument, który wskazuje, czy zmiany należy zatwierdzić, czy zastosować. Otrzymuje również działanie w postaci funkcji lambda, aby wykonać działanie w edytorze 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) }

Element wywołujący może zdecydować, czy zatwierdzić, czy zastosować zmiany. Funkcja action lambda jest anonimową funkcją rozszerzenia w SharedPreferences.Editor, która zwraca wartość Unit zgodnie z jej podpisem. Dlatego właśnie wewnątrz bloku możesz wykonywać tę pracę bezpośrednio w SharedPreferences.Editor.

Podpis SharedPreferences.edit() zawiera słowo kluczowe inline. To słowo kluczowe informuje kompilator Kotlin, że powinien skopiować i wkleić (lub wbudować) skompilowany kod bajtowy funkcji za każdym razem, gdy jest używana. Pozwala to uniknąć nakładów związanych z tworzeniem nowej klasy dla każdego elementu action przy każdym wywołaniu tej funkcji.

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

Użyj Android KTX w swoim projekcie

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

Odlotowe

repositories {
    google()
}

Kotlin

repositories {
    google()
}

Moduły AndroidX

Android KTX dzieli się na moduły, z których każdy zawiera co najmniej jeden pakiet.

W pliku build.gradle aplikacji musisz dodać zależność dla każdego artefaktu modułu. Pamiętaj, aby do artefaktu dołączyć numer wersji. Najnowsze numery wersji znajdziesz w sekcji odpowiadającej poszczególnym artefaktom w tym temacie.

Android KTX zawiera jedno podstawowy moduł udostępniający rozszerzenia Kotlin do interfejsów API platformy oraz 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. Na przykład możesz zastąpić zależność androidx.fragment:fragment elementem androidx.fragment:fragment-ktx. Ta składnia ułatwia zarządzanie wersjami i nie ma dodatkowych wymagań dotyczących deklaracji zależności.

Core KTX

Moduł Core KTX zawiera rozszerzenia do popularnych bibliotek, które wchodzą w skład platformy Androida. Te biblioteki nie mają zależności opartych na Javie, które trzeba dodać do biblioteki build.gradle.

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

Odlotowy

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

Kotlin

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

Oto lista pakietów, które zawiera moduł Core KTX:

Kolekcja KTX

Rozszerzenia kolekcji zawierają funkcje narzędziowe ułatwiające pracę z bibliotekami zbierającymi dane z Androida, które oszczędzają pamięć, w tym ArrayMap, LongSparseArray czy LruCache.

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

Odlotowy

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

Kotlin

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

Rozszerzenia kolekcji korzystają z przeciążania operatorów Kotlin, aby uprościć np. łączenie zbiorów, 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ł KTX z fragmentami zawiera szereg rozszerzeń, które upraszczają interfejs API fragment.

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

Odlotowy

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

Kotlin

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

Dzięki modułowi Fragment KTX możesz uprościć transakcje oparte na fragmentach za pomocą parametrów lambda, np.:

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

Możesz też powiązać z obiektem ViewModel w jednym wierszu, korzystając z 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>()

Cykl życia KTX

KTX w cyklu życia definiuje LifecycleScope dla każdego obiektu Lifecycle. Każda współprogram uruchamiana w tym zakresie zostaje anulowana po zniszczeniu obiektu Lifecycle. Aby uzyskać dostęp do elementu CoroutineScope w: Lifecycle, możesz użyć właściwości lifecycle.coroutineScope lub lifecycleOwner.lifecycleScope.

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

Odlotowy

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

Kotlin

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

Ten przykład pokazuje, jak za pomocą narzędzia lifecycleOwner.lifecycleScope asynchronicznie utworzyć 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

Korzystanie z LiveData może wymagać asynchronicznego obliczania wartości. Możesz na przykład pobrać preferencje użytkownika i wyświetlać je w Twoim interfejsie. W takich przypadkach LiveData KTX udostępnia funkcję konstruktora liveData, która wywołuje funkcję suspend i wyświetla wynik jako obiekt LiveData.

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

Odlotowy

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

Kotlin

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

W poniższym przykładzie loadUser() to funkcja zawieszenia zadeklarowana w innym miejscu. Za pomocą funkcji konstruktora liveData możesz wywołać asynchronicznie loadUser(), a następnie za pomocą 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ółrzędnych z LiveData znajdziesz w artykule o używaniu współrzędnych Kotlina 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 imitujący kotlin.

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

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 rozszerzenia i przekazywania właściwości możesz uzyskać dostęp do argumentów miejsca docelowego i przejść 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 oferuje idiomatyczne wsparcie Kotlina w pracy z paletami kolorów.

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

Odlotowy

dependencies {
    implementation "androidx.palette:palette-ktx:1.0.0"
}

Kotlin

dependencies {
    implementation("androidx.palette:palette-ktx:1.0.0")
}

W przypadku pracy z instancją Palette możesz na przykład pobrać próbkę selected dla danego target miejsca za pomocą operatora get ([ ]):

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

Transmisje reaktywne KTX

Moduł KTX Reaktywnych strumieni umożliwia utworzenie możliwego do obserwowania strumienia LiveData od wydawcy ReactiveStreams.

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

Odlotowy

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

Kotlin

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

Załóżmy na przykład, że używasz bazy danych z niewielką listą użytkowników. W aplikacji wczytujesz bazę danych do pamięci, a następnie wyświetlasz dane użytkownika w interfejsie. Możesz to zrobić za pomocą RxJava. Komponent Jetpack Room może pobierać 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.

Dzięki LiveDataReactiveStreams możesz jednak korzystać z technologii RxJava oraz jej bogatego zestawu operatorów i funkcji harmonogramu pracy, a jednocześnie korzystać z prostoty interfejsu 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ą współgrające z obsługą transakcji w bazie danych.

Aby korzystać z tego modułu, do pliku build.gradle dodaj 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 teraz współrzędnych. W pierwszym przykładzie wykorzystywana jest funkcja suspend, która zwraca listę obiektów User, a drugi – funkcja Flow projektu Kotlina, która zwraca asynchronicznie listę User. Pamiętaj, że gdy używasz Flow, otrzymasz 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 zawijają kod związany z SQL w transakcjach, eliminując niepotrzebny powtarzalny kod.

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

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
}

WyświetlModel KTX

Biblioteka ViewModel KTX zawiera funkcję viewModelScope(), która ułatwia uruchamianie współrzędnych z ViewModel. CoroutineScope jest powiązany z Dispatchers.Main i jest automatycznie anulowany po wyczyszczeniu ViewModel. Możesz używać funkcji viewModelScope(), zamiast tworzyć nowy zakres dla każdego obiektu ViewModel.

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

Odlotowy

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

Kotlin

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

Na przykład ta funkcja viewModelScope() uruchamia współrzędną, która wysyła żądanie sieciowe w wątku w tle. Biblioteka obsługuje całą konfigurację i czyszczenie odpowiednich zakresów:

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ł, do pliku build.gradle aplikacji dodaj ten kod:

Odlotowy

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

Kotlin

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

Zamiast rozszerzenia Worker możesz rozszerzyć zakres CoroutineWorker, który ma nieco inny interfejs API. Jeśli na przykład chcesz utworzyć prosty CoroutineWorker do wykonywania pewnych 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 sekcji Wątki w CoroutineWorker.

WorkManager KTX dodaje też funkcje rozszerzeń do Operations i ListenableFutures, aby zawiesić bieżącą współrzędną.

Oto przykład zawieszania obiektu Operation zwracanego 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ż dołączyć dodatkowe moduły KTX, które istnieją poza AndroidemX.

Firebase – KTX

Niektóre pakiety SDK Firebase na Androida mają 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

Dla pakietów SDK Google Maps Platform na Androida są dostępne rozszerzenia KTX, które pozwalają korzystać z kilku funkcji językowych Kotlin, takich jak funkcje rozszerzeń, parametry nazwane i argumenty domyślne, deklaracje destrukcyjne i współrzędne. Więcej informacji znajdziesz w tych tematach:

Odtwórz Core KTX

Play Core KTX obsługuje połączenia Kotlin w żądaniach jednorazowych oraz Flow do monitorowania stanu aktualizacji przez dodanie funkcji rozszerzeń do SplitInstallManager i AppUpdateManager w bibliotece Play Core.

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

Odlotowe

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 elementu Flow do 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

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

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