Android KTX   Parte de Android Jetpack.

Android KTX es un conjunto de extensiones de Kotlin que se incluyen con Android Jetpack y otras bibliotecas de Android. Las extensiones KTX proporcionan Kotlin conciso e idiomático a Jetpack, la plataforma de Android y otras API. Para ello, esas extensiones aprovechan varias funciones del lenguaje Kotlin, entre las que se incluyen:

  • Funciones de extensión
  • Propiedades de extensión
  • Lambdas
  • Parámetros con nombres
  • Valores predeterminados de parámetros
  • Corrutinas

A modo de ejemplo, cuando trabajes con SharedPreferences, debes crear un editor antes de realizar modificaciones en los datos de preferencias. También debes aplicar o confirmar esos cambios cuando termines de editar, como se muestra en el siguiente ejemplo:

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

Las lambdas de Kotlin son ideales para este caso práctico. Te permiten realizar un enfoque más conciso, ya que pasa un bloque de código para ejecutarse después de crear el editor, lo que permite que se ejecute el código y, luego, que la API de SharedPreferences aplique los cambios automáticamente.

Este es un ejemplo de una de las funciones de Android KTX Core, SharedPreferences.edit, que agrega una función de edición a SharedPreferences. Esta función incluye una marca boolean opcional como su primer argumento que indica si confirmar o aplicar los cambios. También recibe una acción para realizar en el editor SharedPreferences en forma de 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) }
    

El emisor puede elegir confirmar o aplicar los cambios. La lambda action es una función de extensión anónima en SharedPreferences.Editor que muestra Unit, como lo indica su firma. Es por eso que, dentro del bloque, puedes realizar el trabajo de forma directa en el SharedPreferences.Editor.

Por último, la firma SharedPreferences.edit() contiene la palabra clave inline. Esta palabra clave le dice al compilador Kotlin que debe copiar y pegar (o intercalar) el código de bytes compilado para la función cada vez que se utiliza. Esto evita la sobrecarga de crear instancias de una nueva clase por cada action cada vez que se llama a esa función.

Este patrón de pasar código usando lambdas, aplicar valores predeterminados confidenciales que pueden anularse y agregar estos comportamientos a las API existentes mediante funciones de extensión inline es típico de las mejoras proporcionadas por la biblioteca de Android KTX.

Cómo usar Android KTX en tu proyecto

Para comenzar a usar Android KTX, agrega la siguiente dependencia al archivo build.gradle de tu proyecto:

repositories {
        google()
    }
    

Android KTX está organizado en módulos y cada módulo contiene uno o más paquetes.

Debes incluir una dependencia para el artefacto de cada módulo en el archivo build.gradle de tu app. Recuerda agregar el número de versión al artefacto. Por ejemplo, si usas el módulo core-ktx, la dependencia completamente desarrollada será similar a la siguiente:

dependencies {
        implementation 'androidx.core:core-ktx:1.0.1'
    }
    

Módulos

Android KTX incluye un módulo principal único que proporciona extensiones de Kotlin para las API de marcos de trabajo comunes y varias extensiones específicas de dominio.

Con la excepción del módulo principal, todos los artefactos del módulo KTX reemplazan la dependencia subyacente de Java en tu archivo build.gradle. Por ejemplo, puedes reemplazar una dependencia androidx.fragment:fragment por androidx.fragment:fragment-ktx. Esta sintaxis ayuda a administrar mejor las versiones y no agrega requisitos adicionales de declaración de dependencia.

Core KTK

El módulo Core KTX ofrece extensiones para bibliotecas comunes que forman parte del marco de trabajo de Android. Esas bibliotecas no tienen dependencias basadas en Java que debas agregar a build.gradle.

Esta es una lista de los paquetes que se incluyen en el módulo Core KTX:

Fragment KTX

Dependencia: androidx.fragment:fragment-ktx:$version. Asegúrate de definir $version o reemplázala por un valor literal.

El módulo Fragment KTX proporciona varias extensiones para simplificar la API del fragmento. Por ejemplo, puedes simplificar las transacciones del fragmento con lambdas:

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

También puedes vincular a un ViewModel en una línea utilizando los delegados de propiedad viewModels y 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>()
    

Palette KTX

Dependencia: androidx.palette:palette-ktx:$version. Asegúrate de definir $version o reemplázala por un valor literal.

El módulo Palette KTX ofrece la compatibilidad idiomática de Kotlin para trabajar con paletas de colores.

Por ejemplo, cuando trabajas con una instancia Palette, puedes recuperar la muestra selected de un target específico utilizando el operador get ([ ]):

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

SQLite KTX

Dependencia: androidx.sqlite:sqlite-ktx:$version. Asegúrate de definir $version o reemplázala por un valor literal.

Las extensiones de SQLite unen el código relacionado con SQL en las transacciones, lo que elimina una gran cantidad de código estándar, como se muestra en el siguiente ejemplo:

db.transaction {
        // insert data
    }
    

Collection KTX

Dependencia: androidx.collection:collection-ktx:$version. Asegúrate de definir $version o reemplázala por un valor literal.

Las extensiones de Collection contienen funciones de utilidad para trabajar con las bibliotecas de colección eficientes en cuanto a memoria de Android, como ArrayMap, LongParseArray, LruCache y otras.

Las extensiones de Collection aprovechan la sobrecarga del operador de Kotlin para simplificar cuestiones como la concatenación de colecciones, por ejemplo:

// 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
    

ViewModel KTX

Dependencia: androidx.lifecycle:lifecycle-viewmodel-ktx:$version. Define o reemplaza $version para reflejar la última versión del módulo.

La biblioteca de ViewModel KTX ofrece una función viewModelScope() que facilita el lanzamiento de corrutinas desde tu ViewModel. El CoroutineScope está vinculado a Dispatchers.Main y se cancela automáticamente cuando se borra el ViewModel. Puedes usar viewModelScope() en lugar de crear un nuevo alcance para cada ViewModel.

A modo de ejemplo, la siguiente función viewModelScope() lanza una corrutina que realiza una solicitud de red en un subproceso en segundo plano. La biblioteca maneja toda la configuración y la liberación del alcance correspondiente:

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()
    }
    

Reactive Streams KTX

Dependencia: androidx.lifecycle:lifecycle-reactivestreams-ktx:$version. Asegúrate de definir $version o reemplázala por un valor literal.

El módulo Reactive Streams KTX te permite crear una transmisión LiveData observable desde un publicador ReactiveStreams.

Como ejemplo, supone una base de datos con una pequeña lista de usuarios. En tu app, carga la base de datos en la memoria y luego muestra los datos del usuario en tu IU. Para lograr eso, puedes usar RxJava. El componente Room de Jetpack puede recuperar la lista de usuarios como un Flowable. En este caso, también debes administrar la suscripción del publicador de Rx durante la vigencia de tu fragmento o actividad.

Sin embargo, con LiveDataReactiveStreams, puedes beneficiarte de RxJava y su amplio conjunto de operadores y capacidades de programación de trabajo, al mismo tiempo que trabajas con la simplicidad de LiveData. A modo de ejemplo, el siguiente fragmento crea una transmisión observable desde un publicador RxJava Flowable:

val fun getUsersLiveData() : LiveData<List<User>> {
        val users: Flowable<List<User>> = dao.findUsers()
        return LiveDataReactiveStreams.fromPublisher(users)
    }
    

Dependencias:

  • androidx.navigation:navigation-runtime-ktx:$version
  • androidx.navigation:navigation-fragment-ktx:$version
  • androidx.navigation:navigation-ui-ktx:$version

Asegúrate de definir $version o reemplázala por un valor literal.

Cada componente de la biblioteca de Navigation tiene su propia versión de KTX que adapta la API a fin de que sea más breve e idiomática para Kotlin.

Utiliza las funciones de extensión y la delegación de propiedades para acceder a los argumentos de destino y navegar a los destinos, como se muestra en el siguiente ejemplo:

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)
                }
         }
         ...

    }
    

WorkManager KTX

Dependencia: androidx.work:work-runtime-ktx:$version. Asegúrate de definir $version o reemplázala por un valor literal.

WorkManager KTX agrega compatibilidad para las corrutinas de Kotlin sumando funciones de extensión a Operations y ListenableFutures para suspender la corrutina actual, como se muestra en el siguiente ejemplo:

// Inside of a coroutine...

    // Run async operation and suspend until completed.
    WorkManager.getInstance()
            .beginWith(longWorkRequest)
            .enqueue().await()

    // Resume after work completes...
    

Play Core KTX

Dependencia: com.google.android.play:core-ktx:$version. Asegúrate de definir $version o reemplázala por un valor literal.

Play Core KTX admite las corrutinas de Kotlin para solicitudes por única vez y Flow para supervisar las actualizaciones de estado agregando funciones de extensión a SplitInstallManager y AppUpdateManager en la biblioteca de Play Core.

// 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() }
        }
    }
    

Más información

Para obtener más información sobre Android KTX, consulta el video de DevBytes.

Para informar un problema o sugerir una función, usa el seguimiento de problemas de Android KTX.