Android KTX Componente di Android Jetpack.
Android KTX è un insieme di estensioni Kotlin incluse in Android Jetpack e in altre librerie Android. Le estensioni KTX forniscono Kotlin conciso e idiomatico a Jetpack, alla piattaforma Android e ad altre API. A questo scopo, queste estensioni utilizzano diverse funzionalità del linguaggio Kotlin, tra cui:
- Funzioni estensione
- Proprietà dell'estensione
- Lambda
- Parametri denominati
- Valori predefiniti dei parametri
- Coroutine
Ad esempio, quando lavori con
SharedPreferences
, devi
creare un editor
prima di poter apportare modifiche ai dati delle preferenze. Devi inoltre applicare le modifiche o eseguirne il commit al termine delle modifiche, come mostrato nell'esempio seguente:
sharedPreferences
.edit() // create an Editor
.putBoolean("key", value)
.apply() // write to disk asynchronously
Le lambda di Kotlin sono perfette per questo caso d'uso. Ti consentono di adottare un approccio più conciso passando un blocco di codice da eseguire dopo la creazione dell'editor, lasciando che il codice venga eseguito e poi lasciando che l'API SharedPreferences
applichi le modifiche in modo atomico.
Di seguito è riportato un esempio di una delle funzioni principali di Android KTX, SharedPreferences.edit
, che aggiunge una funzione di modifica a SharedPreferences
. Questa funzione prende un
flag facoltativo boolean
come primo argomento che indica se eseguire il commit
o applicare le modifiche. Inoltre, riceve un'azione da eseguire sull'editorSharedPreferences
sotto forma di 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) }
L'utente che chiama può scegliere se applicare o meno le modifiche. La funzione lambda action
è essa stessa una funzione di estensione anonima su SharedPreferences.Editor
che restituisce Unit
, come indicato dalla relativa firma. Ecco perché all'interno del blocco puoi eseguire il lavoro direttamente su SharedPreferences.Editor
.
Infine, la firma SharedPreferences.edit()
contiene la parola chiave inline
.
Questa parola chiave indica al compilatore Kotlin di copiare e incollare (o
inserire in linea) il bytecode compilato per la funzione ogni volta che viene utilizzata.
In questo modo si evita l'overhead dell'inizializzazione di una nuova classe per ogni action
ogni
volta che viene chiamata questa funzione.
Questo pattern di passaggio del codice tramite lambda, applicazione di valori predefiniti ragionevoli che possono essere sostituiti e aggiunta di questi comportamenti alle API esistenti utilizzando le funzioni di estensione inline
è tipico dei miglioramenti forniti dalla libreria Android KTX.
Utilizzare Android KTX nel progetto
Per iniziare a utilizzare Android KTX, aggiungi la seguente dipendenza al file build.gradle
del progetto:
Groovy
repositories { google() }
Kotlin
repositories { google() }
Moduli AndroidX
Android KTX è organizzato in moduli, ognuno dei quali contiene uno o più pacchetti.
Devi includere una dipendenza per ogni artefatto del modulo nel file build.gradle
dell'app. Ricordati di aggiungere il numero di versione all'elemento.
Puoi trovare i numeri di versione più recenti nella sezione corrispondente di ciascun elemento
in questo argomento.
Android KTX contiene un modulo principale singolo che fornisce estensioni Kotlin per le API del framework comuni e diverse estensioni specifiche per dominio.
Ad eccezione del modulo principale, tutti gli elementi del modulo KTX sostituiscono la dipendenza Java di base nel file build.gradle
. Ad esempio, puoi sostituire una dipendenza androidx.fragment:fragment
con androidx.fragment:fragment-ktx
. Questa sintassi consente di gestire meglio il versionamento e non aggiunge ulteriori requisiti di dichiarazione delle dipendenze.
Core KTX
Il modulo Core KTX fornisce estensioni per le librerie comuni che fanno parte del framework Android. Queste librerie non hanno dipendenze basate su Java che devi aggiungere a build.gradle
.
Per includere questo modulo, aggiungi quanto segue al file build.gradle
dell'app:
Alla moda
dependencies { implementation "androidx.core:core-ktx:1.13.1" }
Kotlin
dependencies { implementation("androidx.core:core-ktx:1.13.1") }
Ecco un elenco dei pacchetti contenuti nel modulo Core KTX:
- 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
Collezione KTX
Le estensioni Collection contengono funzioni di utilità per lavorare con le librerie di raccolte di Android che consentono di risparmiare memoria, tra cui ArrayMap
, LongSparseArray
,
LruCache
e altre.
Per utilizzare questo modulo, aggiungi quanto segue al file build.gradle
della tua app:
Groovy
dependencies { implementation "androidx.collection:collection-ktx:1.4.4" }
Kotlin
dependencies { implementation("androidx.collection:collection-ktx:1.4.4") }
Le estensioni di raccolta sfruttano il sovraccarico degli operatori di Kotlin per semplificare operazioni come la concatenazione delle raccolte, come mostrato nell'esempio seguente:
// 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
KTX frammento
Il modulo KTX dei frammenti fornisce una serie di estensioni per semplificare l'API dei frammenti.
Per includere questo modulo, aggiungi quanto segue al file build.gradle
dell'app:
Alla moda
dependencies { implementation "androidx.fragment:fragment-ktx:1.8.3" }
Kotlin
dependencies { implementation("androidx.fragment:fragment-ktx:1.8.3") }
Con il modulo Fragment KTX, puoi semplificare le transazioni dei frammenti con i lambda, ad esempio:
fragmentManager().commit {
addToBackStack("...")
setCustomAnimations(
R.anim.enter_anim,
R.anim.exit_anim)
add(fragment, "...")
}
Puoi anche eseguire il binding a un ViewModel
in una riga utilizzando i delegati delle proprietà viewModels
e
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
Lifecycle KTX definisce un LifecycleScope
per ogni oggetto
Lifecycle
. Qualsiasi coroutine avviata in questo ambito viene annullata quando Lifecycle
viene distrutta. Puoi accedere al CoroutineScope
del Lifecycle
utilizzando le proprietà lifecycle.coroutineScope
o lifecycleOwner.lifecycleScope
.
Per includere questo modulo, aggiungi quanto segue al file build.gradle
dell'app:
Alla moda
dependencies { implementation "androidx.lifecycle:lifecycle-runtime-ktx:2.8.5" }
Kotlin
dependencies { implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.8.5") }
L'esempio seguente mostra come utilizzare lifecycleOwner.lifecycleScope
per creare testo precalcolato in modo asincrono:
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
Quando utilizzi LiveData, potresti dover calcolare i valori in modo asincrono. Ad esempio, potresti voler recuperare le preferenze di un utente e mostrarle nella tua UI. Per questi casi, LiveData KTX fornisce una funzione di compilatore liveData
che chiama una funzione suspend
e restituisce il risultato come oggetto LiveData
.
Per includere questo modulo, aggiungi quanto segue al file build.gradle
dell'app:
Alla moda
dependencies { implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.8.6" }
Kotlin
dependencies { implementation("androidx.lifecycle:lifecycle-livedata-ktx:2.8.6") }
Nell'esempio seguente, loadUser()
è una funzione di sospensione dichiarata altrove.
Puoi utilizzare la funzione di compilatore liveData
per chiamare loadUser()
in modo asincrono,
quindi utilizzare emit()
per emettere il risultato:
val user: LiveData<User> = liveData {
val data = database.loadUser() // loadUser is a suspend function.
emit(data)
}
Per saperne di più sull'utilizzo delle coroutine con LiveData
, consulta
Utilizzare le coroutine Kotlin con i componenti dell'architettura.
Navigation KTX
Ogni componente della libreria Navigation ha la propria versione KTX che adatta l'API in modo che sia più concisa e in conformità con le convenzioni di Kotlin.
Per includere questi moduli, aggiungi quanto segue al file build.gradle
dell'app:
Alla moda
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") }
Utilizza le funzioni di estensione e la delega delle proprietà per accedere agli argomenti destinazione e passare alle destinazioni, come mostrato nell'esempio seguente:
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
Il modulo KTX Palette offre il supporto idiomatico di Kotlin per lavorare con le tavolozze di colori.
Per utilizzare questo modulo, aggiungi quanto segue al file build.gradle
della tua app:
Alla moda
dependencies { implementation "androidx.palette:palette-ktx:1.0.0" }
Kotlin
dependencies { implementation("androidx.palette:palette-ktx:1.0.0") }
Ad esempio, quando lavori con un'istanza Palette
, puoi recuperare il campione selected
per un determinato target
utilizzando l'operatore get ([ ]
):
val palette = Palette.from(bitmap).generate()
val swatch = palette[target]
Reactive Streams KTX
Il modulo KTX Reactive Streams ti consente di creare uno stream LiveData
osservabile da un publisher ReactiveStreams
.
Per includere questo modulo, aggiungi quanto segue al file build.gradle
dell'app:
Alla moda
dependencies { implementation "androidx.lifecycle:lifecycle-reactivestreams-ktx:2.8.5" }
Kotlin
dependencies { implementation("androidx.lifecycle:lifecycle-reactivestreams-ktx:2.8.5") }
Ad esempio, supponiamo che un database abbia un piccolo elenco di utenti. Nella tua app, carichi il database in memoria e quindi visualizzi i dati utente nella UI. Per ottenere
questo risultato, potresti utilizzare RxJava.
Il componente Jetpack Room
può recuperare
l'elenco degli utenti come Flowable
. In questo caso, devi anche gestire l'abbonamento del publisher Rx per tutta la durata del frammento o dell'attività.
Tuttavia, con LiveDataReactiveStreams
, puoi trarre vantaggio da RxJava e dal suo ricco set di operatori e funzionalità di pianificazione del lavoro utilizzando al contempo la semplicità di LiveData
, come mostrato nell'esempio seguente:
val fun getUsersLiveData() : LiveData<List<User>> {
val users: Flowable<List<User>> = dao.findUsers()
return LiveDataReactiveStreams.fromPublisher(users)
}
Sala KTX
Le estensioni Room aggiungono il supporto delle coroutine per le transazioni di database.
Per utilizzare questo modulo, aggiungi quanto segue al file build.gradle
dell'app:
Alla moda
dependencies { implementation "androidx.room:room-ktx:2.6.1" }
Kotlin
dependencies { implementation("androidx.room:room-ktx:2.6.1") }
Ecco un paio di esempi in cui Room ora utilizza le coroutine. Il primo esempio
utilizza una funzione suspend
per restituire un elenco di oggetti User
, mentre il secondo
utilizza Flow
di Kotlin
per restituire in modo asincrono l'elenco User
. Tieni presente che, quando utilizzi Flow
, ti viene anche comunicata qualsiasi modifica nelle tabelle su cui esegui query.
@Query("SELECT * FROM Users")
suspend fun getUsers(): List<User>
@Query("SELECT * FROM Users")
fun getUsers(): Flow<List<User>>
SQLite KTX
Le estensioni SQLite inseriscono il codice relativo a SQL nelle transazioni, eliminando molto codice boilerplate.
Per utilizzare questo modulo, aggiungi quanto segue al file build.gradle
dell'app:
Alla moda
dependencies { implementation "androidx.sqlite:sqlite-ktx:2.4.0" }
Kotlin
dependencies { implementation("androidx.sqlite:sqlite-ktx:2.4.0") }
Ecco un esempio di utilizzo dell'estensione transaction
per eseguire una transazione del database:
db.transaction {
// insert data
}
ViewModel KTX
La libreria KTX ViewModel fornisce una funzione viewModelScope()
che rende
più semplice l'avvio di coroutine da ViewModel
. CoroutineScope
è associato a Dispatchers.Main
e viene annullato automaticamente quando ViewModel
viene deselezionato. Puoi utilizzare viewModelScope()
anziché creare un nuovo ambito per ogni ViewModel
.
Per includere questo modulo, aggiungi quanto segue al file build.gradle
dell'app:
Alla moda
dependencies { implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.8.5" }
Kotlin
dependencies { implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.8.5") }
Ad esempio, la seguente funzione viewModelScope()
avvia una coroutine
che effettua una richiesta di rete in un thread in background. La libreria gestisce tutta la configurazione e la relativa eliminazione dell'ambito:
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 offre un'assistenza di primo livello per le coroutine.
Per includere questo modulo, aggiungi quanto segue al file build.gradle
dell'app:
Alla moda
dependencies { implementation "androidx.work:work-runtime-ktx:2.9.1" }
Kotlin
dependencies { implementation("androidx.work:work-runtime-ktx:2.9.1") }
Anziché estendere Worker
, ora puoi estendere CoroutineWorker
, che ha un'API leggermente diversa. Ad esempio, se vuoi creare un CoroutineWorker
semplice per eseguire alcune operazioni di rete, puoi fare quanto segue:
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()
}
}
Per ulteriori informazioni sull'utilizzo di CoroutineWorker
, consulta
Threading in CoroutineWorker.
WorkManager KTX aggiunge anche funzioni di estensione a Operations
e
ListenableFutures
per sospendere la coroutine corrente.
Ecco un esempio che sospende il valore Operation
restituito da enqueue()
:
// Inside of a coroutine...
// Run async operation and suspend until completed.
WorkManager.getInstance()
.beginWith(longWorkRequest)
.enqueue().await()
// Resume after work completes...
Altri moduli KTX
Puoi anche includere moduli KTX aggiuntivi al di fuori di AndroidX.
KTX Firebase
Alcuni SDK Firebase per Android dispongono di librerie di estensioni Kotlin che consentono di scrivere codice Kotlin idiomatico quando utilizzi Firebase nella tua app. Per ulteriori informazioni, consulta i seguenti argomenti:
Google Maps Platform KTX
Esistono estensioni KTX disponibili per gli SDK Android di Google Maps Platform che consentono di sfruttare diverse funzionalità del linguaggio Kotlin, come funzioni di estensione, parametri denominati e argomenti predefiniti, dichiarazioni di destrutturazione e coroutine. Per ulteriori informazioni, consulta i seguenti argomenti:
Play Core KTX
Play Core KTX aggiunge il supporto delle coroutine Kotlin per le richieste una tantum e Flow per il monitoraggio degli aggiornamenti dello stato aggiungendo funzioni di estensione a SplitInstallManager
e AppUpdateManager
nella libreria Play Core.
Per includere questo modulo, aggiungi quanto segue al file build.gradle
dell'app:
Groovy
dependencies { implementation "com.google.android.play:core-ktx:1.8.1" }
Kotlin
dependencies { implementation("com.google.android.play:core-ktx:1.8.1") }
Ecco un esempio di Flow
di monitoraggio dello stato:
// 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()
}
}
Ulteriori informazioni
Per scoprire di più su Android KTX, guarda il video DevBytes.
Per segnalare un problema o suggerire una funzionalità, utilizza lo strumento di monitoraggio dei problemi di Android KTX.