Android KTX   Parte 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, idiomatico a Jetpack, alla piattaforma Android e ad altre API. A questo scopo, queste estensioni sfruttano diverse funzionalità del linguaggio Kotlin, tra cui le seguenti:

  • Funzioni di 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 anche applicare o eseguire il commit di queste modifiche al termine della modifica, come mostrato nel seguente esempio:

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

Le espressioni lambda 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, consentendo l'esecuzione del codice e quindi consentendo all'API SharedPreferences di applicare le modifiche in modo atomico.

Ecco un esempio di una delle funzioni di Android KTX Core, SharedPreferences.edit, che aggiunge una funzione di modifica a SharedPreferences. Questa funzione accetta un flag boolean facoltativo come primo argomento che indica se eseguire il commit o applicare le modifiche. Riceve anche un'azione da eseguire nell'editor SharedPreferences 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) }

Il chiamante può scegliere se eseguire il commit o applicare le modifiche. La action lambda è una funzione di estensione anonima su SharedPreferences.Editor che restituisce Unit, come indicato dalla sua firma. Per questo motivo, 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 inline) il bytecode compilato per la funzione ogni volta che viene utilizzata. In questo modo si evita il sovraccarico di istanziare una nuova classe per ogni action ogni volta che viene chiamata questa funzione.

Questo pattern di passaggio del codice utilizzando le espressioni lambda, l'applicazione di valori predefiniti ragionevoli che possono essere sostituiti e l'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 della tua app. Ricordati di aggiungere il numero di versione all'artefatto. Puoi trovare i numeri di versione più recenti nella sezione corrispondente di ogni artefatto in questo argomento.

Android KTX contiene un unico modulo principale che fornisce estensioni Kotlin per le API del framework comuni e diverse estensioni specifiche per il dominio.

Ad eccezione del modulo principale, tutti gli artefatti del modulo KTX sostituiscono la dipendenza Java sottostante 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 controllo delle versioni 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:

Groovy

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

Kotlin

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

Di seguito è riportato un elenco dei pacchetti contenuti nel modulo Core KTX:

Collection KTX

Le estensioni Collection contengono funzioni di utilità per lavorare con le librerie di raccolta efficienti in termini di memoria di Android, tra cui ArrayMap, LongSparseArray, LruCache e altre.

Per utilizzare questo modulo, aggiungi quanto segue al file build.gradle dell'app:

Groovy

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

Kotlin

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

Le estensioni delle raccolte sfruttano l'overload 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

Fragment KTX

Il modulo Fragment KTX fornisce una serie di estensioni per semplificare l'API Fragment.

Per includere questo modulo, aggiungi quanto segue al file build.gradle dell'app:

Alla moda

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

Kotlin

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

Con il modulo Fragment KTX, puoi semplificare le transazioni dei fragment con le espressioni 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 distrutto. Puoi accedere a CoroutineScope di Lifecycle utilizzando le proprietà lifecycle.coroutineScope o lifecycleOwner.lifecycleScope.

Per includere questo modulo, aggiungi quanto segue al file build.gradle dell'app:

Groovy

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

Kotlin

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

Il seguente esempio 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 creazione 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:

Groovy

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

Kotlin

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

Nell'esempio seguente, loadUser() è una funzione di sospensione dichiarata altrove. Puoi utilizzare la funzione di creazione liveData per chiamare loadUser() in modo asincrono, e poi 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.

Ogni componente della libreria Navigation ha la propria versione KTX che adatta l'API per renderla più concisa e idiomatica per Kotlin.

Per includere questi moduli, aggiungi quanto segue al file build.gradle dell'app:

Groovy

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

Kotlin

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

Utilizza le funzioni di estensione e la delega delle proprietà per accedere agli argomenti della 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 Palette KTX offre il supporto idiomatico di Kotlin per l'utilizzo delle tavolozze dei colori.

Per utilizzare questo modulo, aggiungi quanto segue al file build.gradle dell'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 Reactive Streams KTX consente di creare un flusso LiveData osservabile da un publisher ReactiveStreams.

Per includere questo modulo, aggiungi quanto segue al file build.gradle dell'app:

Groovy

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

Kotlin

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

Ad esempio, supponiamo di avere un database con un piccolo elenco di utenti. Nella tua app, carichi il database in memoria e poi visualizzi i dati utente nella UI. Per ottenere questo risultato, puoi utilizzare RxJava. Il componente Jetpack Room può recuperare l'elenco utenti come Flowable. In questo scenario, devi anche gestire l'abbonamento dell'editore Rx per tutta la durata del fragment o dell'attività.

Con LiveDataReactiveStreams, tuttavia, puoi usufruire di RxJava e del suo ricco set di operatori e funzionalità di pianificazione del lavoro, lavorando anche con 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)
}

Room 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:

Groovy

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

Kotlin

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

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, ricevi una notifica anche per eventuali modifiche alle tabelle che stai interrogando.

@Query("SELECT * FROM Users")
suspend fun getUsers(): List<User>

@Query("SELECT * FROM Users")
fun getUsers(): Flow<List<User>>

SQLite KTX

Le estensioni SQLite racchiudono il codice correlato a SQL nelle transazioni, eliminando gran parte del codice boilerplate.

Per utilizzare questo modulo, aggiungi quanto segue al file build.gradle dell'app:

Alla moda

dependencies {
    implementation "androidx.sqlite:sqlite-ktx:2.5.2"
}

Kotlin

dependencies {
    implementation("androidx.sqlite:sqlite-ktx:2.5.2")
}

Ecco un esempio di utilizzo dell'estensione transaction per eseguire una transazione di database:

db.transaction {
    // insert data
}

ViewModel KTX

La libreria ViewModel KTX fornisce una funzione viewModelScope() che semplifica l'avvio di coroutine dal tuo ViewModel. L'CoroutineScope è associato a Dispatchers.Main e viene annullato automaticamente quando ViewModel viene cancellato. Puoi utilizzare viewModelScope() anziché creare un nuovo ambito per ogni ViewModel.

Per includere questo modulo, aggiungi quanto segue al file build.gradle dell'app:

Groovy

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

Kotlin

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

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 l'eliminazione dell'ambito corrispondente:

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 supporto di prima classe 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.10.2"
}

Kotlin

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

Anziché estendere Worker, ora puoi estendere CoroutineWorker, che ha un'API leggermente diversa. Ad esempio, se vuoi creare un semplice CoroutineWorker per eseguire alcune operazioni di rete, puoi procedere nel seguente modo:

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 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 che non fanno parte di AndroidX.

Firebase KTX

Alcuni degli SDK Firebase per Android hanno librerie di estensioni Kotlin che ti consentono di scrivere codice Kotlin idiomatico quando utilizzi Firebase nella tua app. Per maggiori informazioni, consulta i seguenti argomenti:

Google Maps Platform KTX

Sono disponibili estensioni KTX per gli SDK Android di Google Maps Platform che ti consentono di sfruttare diverse funzionalità del linguaggio Kotlin, come funzioni di estensione, parametri denominati e argomenti predefiniti, dichiarazioni di destrutturazione e coroutine. Per maggiori informazioni, consulta i seguenti argomenti:

Play Core KTX

Play Core KTX aggiunge il supporto per le coroutine Kotlin per le richieste una tantum e per Flow per il monitoraggio degli aggiornamenti di 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 l'Issue Tracker di Android KTX.