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łe, idiotyczne narzędzie 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
- Funkcje lambda
- Parametry nazwane
- Domyślne wartości parametru
- 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) }
Element wywołujący może wybrać, czy zatwierdzić, czy zastosować zmiany. Funkcja lambda action
jest anonimową funkcją rozszerzenia funkcji SharedPreferences.Editor
, która zwraca Unit
, zgodnie z jej sygnaturą. Dlatego w bloku SharedPreferences.Editor
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ść:
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 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 musisz dodać do pliku build.gradle
.
Aby uwzględnić ten moduł, do pliku build.gradle
aplikacji dodaj te informacje:
dependencies { implementation "androidx.core:core-ktx:1.15.0" }
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 narzędziowe umożliwiające korzystanie z bibliotek zbierania danych Androida, które oszczędzają pamięć, w tym ArrayMap
, LongSparseArray
czy LruCache
.
Aby korzystać z tego modułu, dodaj do pliku build.gradle
aplikacji te elementy:
dependencies { implementation "androidx.collection:collection-ktx:1.4.5" }
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ł 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:
dependencies {
implementation "androidx.fragment:fragment-ktx:1.8.3"
}
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ż nawiązać połączenie z elementem ViewModel
w jednym wierszu, używając delegowanych 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
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 te informacje:
dependencies {
implementation "androidx.lifecycle:lifecycle-runtime-ktx:2.8.7"
}
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ł, do pliku build.gradle
aplikacji dodaj te informacje:
dependencies {
implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.8.7"
}
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 je uwzględnić, dodaj do pliku build.gradle
aplikacji te moduły:
dependencies { implementation "androidx.navigation:navigation-runtime-ktx:2.8.8" implementation "androidx.navigation:navigation-fragment-ktx:2.8.8" implementation "androidx.navigation:navigation-ui-ktx:2.8.8" }
dependencies { implementation("androidx.navigation:navigation-runtime-ktx:2.8.8") implementation("androidx.navigation:navigation-fragment-ktx:2.8.8") implementation("androidx.navigation:navigation-ui-ktx:2.8.8") }
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)
}
}
...
}
Paleta KTX
Moduł Palette KTX oferuje idiomatyczne wsparcie Kotlina w pracy z paletami kolorów.
Aby korzystać z tego modułu, dodaj do pliku build.gradle
aplikacji te elementy:
dependencies {
implementation "androidx.palette:palette-ktx:1.0.0"
}
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ł 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:
dependencies {
implementation "androidx.lifecycle:lifecycle-reactivestreams-ktx:2.8.7"
}
dependencies {
implementation("androidx.lifecycle:lifecycle-reactivestreams-ktx:2.8.7")
}
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. 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, do pliku build.gradle
dodaj te elementy:
dependencies { implementation "androidx.room:room-ktx:2.6.1" }
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:
dependencies {
implementation "androidx.sqlite:sqlite-ktx:2.4.0"
}
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 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
. Zamiast tworzyć nowy zakres dla każdego ViewModel
, możesz użyć operatora viewModelScope()
.
Aby uwzględnić ten moduł, do pliku build.gradle
aplikacji dodaj te informacje:
dependencies {
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.8.5"
}
dependencies {
implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.8.5")
}
Na przykład ta funkcja viewModelScope()
uruchamia współrzędną, która wysyła żądanie sieciowe w 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 najwyższej klasy obsługę współprogramów.
Aby uwzględnić ten moduł, do pliku build.gradle
aplikacji dodaj te informacje:
dependencies {
implementation "androidx.work:work-runtime-ktx:2.9.1"
}
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 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 tematach:
Play 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 te informacje:
dependencies { implementation "com.google.android.play:core-ktx:1.8.1" }
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.