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 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 inline
jest 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 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 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 rdzenia, który udostępnia rozszerzenia Kotlina dla typowych interfejsów API frameworku 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:
Groovy
dependencies { implementation "androidx.core:core-ktx:1.15.0" }
Kotlin
dependencies { implementation("androidx.core:core-ktx:1.15.0") }
Oto lista pakietów zawartych w module KTX Core:
- 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 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ł, dodaj do pliku build.gradle
aplikacji te informacje:
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 viewModels
i activityViewModels
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ł, dodaj do pliku build.gradle
aplikacji te informacje:
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.
Navigation KTX
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:
Groovy
dependencies { implementation "androidx.navigation:navigation-runtime-ktx:2.8.4" implementation "androidx.navigation:navigation-fragment-ktx:2.8.4" implementation "androidx.navigation:navigation-ui-ktx:2.8.4" }
Kotlin
dependencies { implementation("androidx.navigation:navigation-runtime-ktx:2.8.4") implementation("androidx.navigation:navigation-fragment-ktx:2.8.4") implementation("androidx.navigation:navigation-ui-ktx:2.8.4") }
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 elementy:
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ł, dodaj do pliku build.gradle
aplikacji te informacje:
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 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 elementy:
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 ustawienia i odpowiednie oczyszczanie 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ć Worker
możesz teraz rozszerzać 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 Operations
i
ListenableFutures
, aby zawiesić bieżącą funkcję sterującą.
Oto przykład, który zawiesza działanie funkcji Operation
zwracanej 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 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 SplitInstallManager
i AppUpdateManager
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ę, użyj narzędzia do śledzenia problemów z Androidem KTX.