Diez características de Kotlin para impulsar el desarrollo de Android

Publicado: 2022-03-11

Introducción

Hace un tiempo, Tomasz presentó el desarrollo de Kotlin en Android. Para recordarle: Kotlin es un nuevo lenguaje de programación desarrollado por Jetbrains, la compañía detrás de uno de los IDE de Java más populares, IntelliJ IDEA. Al igual que Java, Kotlin es un lenguaje de propósito general. Dado que cumple con el código de bytes de Java Virtual Machine (JVM), se puede usar junto con Java y no tiene una sobrecarga de rendimiento.

En este artículo, cubriré las 10 funciones más útiles para impulsar su desarrollo de Android.

Nota : en el momento de escribir este artículo, las versiones reales eran Android Studio 2.1.1. y Kotlin 1.0.2.

kotlin

¿Cansado del código Java interminable? Prueba Kotlin y ahorra tiempo y cordura.
Pío

Configuración de Kotlin

Dado que Kotlin es desarrollado por JetBrains, es compatible tanto con Android Studio como con IntelliJ.

El primer paso es instalar el complemento de Kotlin. Después de hacerlo con éxito, habrá nuevas acciones disponibles para convertir su Java a Kotlin. Dos nuevas opciones son:

  1. Cree un nuevo proyecto de Android y configure Kotlin en el proyecto.
  2. Agregue compatibilidad con Kotlin a un proyecto de Android existente.

Para saber cómo crear un nuevo proyecto de Android, consulte la guía oficial paso a paso. Para agregar compatibilidad con Kotlin a un proyecto recién creado o existente, abra el cuadro de diálogo de acción de búsqueda con Command + Shift + A en Mac o Ctrl + Shift + A en Windows/Linux e invoque la acción Configure Kotlin in Project .

Para crear una nueva clase de Kotlin, seleccione:

  • File > New > Kotlin file/class , o
  • File > New > Kotlin activity

Alternativamente, puede crear una clase Java y convertirla a Kotlin usando la acción mencionada anteriormente. Recuerde, puede usarlo para convertir cualquier clase, interfaz, enumeración o anotación, y esto puede usarse para comparar Java fácilmente con el código de Kotlin.

Otro elemento útil que ahorra mucho tecleo son las extensiones de Kotlin. Para usarlos, debe aplicar otro complemento en el archivo build.gradle de su módulo:

 apply plugin: 'kotlin-android-extensions'

Advertencia : si está utilizando la acción del complemento Kotlin para configurar su proyecto, colocará el siguiente código en su archivo build.gradle de nivel superior:

 buildscript { ext.kotlin_version = '1.0.2' repositories { jcenter() } dependencies { classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files } }

Esto hará que la extensión no funcione. Para solucionarlo, simplemente copie ese código en cada uno de los módulos del proyecto en el que desee utilizar Kotlin.

Si configura todo correctamente, debería poder ejecutar y probar su aplicación de la misma manera que lo haría en un proyecto estándar de Android, pero ahora usando Kotlin.

Ahorro de tiempo con Kotlin

Entonces, comencemos describiendo algunos aspectos clave del lenguaje Kotlin y brindando consejos sobre cómo puede ahorrar tiempo usándolo en lugar de Java.

Característica #1: Importación de diseño estático

Uno de los códigos repetitivos más comunes en Android es usar la función findViewById() para obtener referencias a sus vistas en Actividades o Fragmentos.

Hay soluciones, como la biblioteca Butterknife, que ahorran algo de escritura, pero Kotlin da un paso más al permitirle importar todas las referencias a las vistas desde el diseño con una sola importación.

Por ejemplo, considere el siguiente diseño XML de actividad:

 <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:andro xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="co.ikust.kotlintest.MainActivity"> <TextView android: android:layout_width="wrap_content" android:layout_height="wrap_content"/> </RelativeLayout>

Y el código de actividad que lo acompaña:

 package co.ikust.kotlintest import android.support.v7.app.AppCompatActivity import android.os.Bundle import kotlinx.android.synthetic.main.activity_main.* class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) helloWorldTextView.text = "Hello World!" } }

Para obtener las referencias de todas las vistas en el diseño con una ID definida, use la extensión de Android Kotlin Anko. Recuerde escribir esta declaración de importación:

 import kotlinx.android.synthetic.main.activity_main.*

Tenga en cuenta que no necesita escribir punto y coma al final de las líneas en Kotlin porque son opcionales.

El TextView from layout se importa como una instancia de TextView con el nombre igual al ID de la vista. No se confunda con la sintaxis, que se usa para establecer la etiqueta:

 helloWorldTextView.text = "Hello World!"

Cubriremos eso en breve.

Advertencias :

  • Asegúrese de importar el diseño correcto; de lo contrario, las referencias de vista importadas tendrán un valor null .
  • Al usar fragmentos, asegúrese de que las referencias de vista importadas se usen después de la llamada a la función onCreateView() . Importe el diseño en la función onCreateView() y use las referencias de vista para configurar la interfaz de usuario en onViewCreated() . Las referencias no se asignarán antes de que finalice el método onCreateView() .

Característica #2: Escribir clases POJO con Kotlin

Algo que ahorrará la mayor parte del tiempo con Kotlin es escribir las clases POJO (Plain Old Java Object) que se utilizan para almacenar datos. Por ejemplo, en el cuerpo de solicitud y respuesta de una API RESTful. En las aplicaciones que dependen de la API RESTful, habrá muchas clases como esa.

En Kotlin, se hace mucho por ti y la sintaxis es concisa. Por ejemplo, considere la siguiente clase en Java:

 public class User { private String firstName; private String lastName; public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } }

Cuando trabaje con Kotlin, no tiene que volver a escribir la palabra clave pública. Por defecto, todo es de ámbito público. Por ejemplo, si desea declarar una clase, simplemente escriba:

 class MyClass { }

El equivalente del código Java anterior en Kotlin:

 class User { var firstName: String? = null var lastName: String? = null }

Bueno, eso ahorra mucho escribir, ¿no? Repasemos el código de Kotlin.

Kotlin ahorra mucho tipeo

Al definir variables en Kotlin, hay dos opciones:

  • Variables mutables, definidas por la palabra clave var .
  • Variables inmutables, definidas por la palabra clave val .

Lo siguiente a tener en cuenta es que la sintaxis difiere un poco de Java; primero, declara el nombre de la variable y luego sigue con el tipo. Además, de forma predeterminada, las propiedades son tipos no nulos, lo que significa que no pueden aceptar un valor null . Para definir una variable para aceptar un valor null , se debe agregar un signo de interrogación después del tipo. Hablaremos de esto y de la seguridad nula en Kotlin más adelante.

Otra cosa importante a tener en cuenta es que Kotlin no tiene la capacidad de declarar campos para la clase; sólo se pueden definir propiedades. Entonces, en este caso, firstName y lastName son propiedades a las que se les han asignado métodos getter/setter predeterminados. Como se mencionó, en Kotlin, ambos son públicos de forma predeterminada.

Los accesores personalizados se pueden escribir, por ejemplo:

 class User { var firstName: String? = null var lastName: String? = null val fullName: String? get() firstName + " " + lastName }

Desde el exterior, cuando se trata de sintaxis, las propiedades se comportan como campos públicos en Java:

 val userName = user.firstName user.firstName = "John"

Tenga en cuenta que la nueva propiedad fullName es de solo lectura (definida por la palabra clave val ) y tiene un captador personalizado; simplemente agrega nombre y apellido.

Todas las propiedades en Kotlin deben asignarse cuando se declaran o están en un constructor. Hay algunos casos en los que eso no es conveniente; por ejemplo, para propiedades que se inicializarán mediante inyección de dependencia. En ese caso, se puede usar un modificador lateinit . Aquí hay un ejemplo:

 class MyClass { lateinit var firstName : String; fun inject() { firstName = "John"; } }

Se pueden encontrar más detalles sobre las propiedades en la documentación oficial.

Característica #3: Herencia de clases y constructores

Kotlin también tiene una sintaxis más concisa cuando se trata de constructores.

Constructores

Las clases de Kotlin tienen un constructor primario y uno o más constructores secundarios. Un ejemplo de definición de un constructor primario:

 class User constructor(firstName: String, lastName: String) { }

El constructor principal va después del nombre de la clase en la definición de la clase. Si el constructor principal no tiene anotaciones ni modificadores de visibilidad, se puede omitir la palabra clave del constructor:

 class Person(firstName: String) { }

Tenga en cuenta que un constructor principal no puede tener ningún código; cualquier inicialización debe hacerse en el bloque de código de init :

 class Person(firstName: String) { init { //perform primary constructor initialization here } }

Además, se puede usar un constructor primario para definir e inicializar propiedades:

 class User(var firstName: String, var lastName: String) { // ... }

Al igual que las normales, las propiedades definidas desde un constructor principal pueden ser inmutables ( val ) o mutables ( var ).

Las clases también pueden tener constructores secundarios; la sintaxis para definir uno es la siguiente:

 class User(var firstName: String, var lastName) { constructor(name: String, parent: Person) : this(name) { parent.children.add(this) } }

Tenga en cuenta que cada constructor secundario debe delegar en un constructor principal. Esto es similar a Java, que usa this palabra clave:

 class User(val firstName: String, val lastName: String) { constructor(firstName: String) : this(firstName, "") { //... } }

Al crear instancias de clases, tenga en cuenta que Kotlin no tiene new palabras clave, al igual que Java. Para crear instancias de la clase User mencionada anteriormente, utilice:

 val user = User("John", "Doe)

Introducción a la herencia

En Kotlin, todas las clases se extienden desde Any , que es similar a Object en Java. Por defecto, las clases están cerradas, como las clases finales en Java. Entonces, para extender una clase, debe declararse como open o abstract :

 open class User(val firstName, val lastName) class Administrator(val firstName, val lastName) : User(firstName, lastName)

Tenga en cuenta que debe delegar en el constructor predeterminado de la clase extendida, que es similar a llamar al método super() en el constructor de una nueva clase en Java.

Para más detalles sobre las clases, consulta la documentación oficial.

Característica #4: Expresiones Lambda

Las expresiones lambda, introducidas con Java 8, son una de sus funciones favoritas. Sin embargo, las cosas no son tan brillantes en Android, ya que todavía solo es compatible con Java 7 y parece que Java 8 no será compatible en el corto plazo. Por lo tanto, las soluciones alternativas, como Retrolambda, traen expresiones lambda a Android.

Con Kotlin, no se requieren bibliotecas adicionales ni soluciones alternativas.

Funciones en Kotlin

Comencemos repasando rápidamente la sintaxis de la función en Kotlin:

 fun add(x: Int, y: Int) : Int { return x + y }

El valor de retorno de la función se puede omitir y, en ese caso, la función devolverá Int . Vale la pena repetir que todo en Kotlin es un objeto, extendido desde Any y no hay tipos primitivos.

Un argumento de la función puede tener un valor predeterminado, por ejemplo:

 fun add(x: Int, y: Int = 1) : Int { return x + y; }

En ese caso, la función add() se puede invocar pasando solo el argumento x . El código Java equivalente sería:

 int add(int x) { Return add(x, 1); } int add(int x, int y) { return x + y; }

Otra cosa buena cuando se llama a una función es que se pueden usar argumentos con nombre. Por ejemplo:

 add(y = 12, x = 5)

Para obtener más detalles sobre las funciones, consulte la documentación oficial.

Uso de expresiones Lambda en Kotlin

Las expresiones lambda en Kotlin se pueden ver como funciones anónimas en Java, pero con una sintaxis más concisa. Como ejemplo, mostremos cómo implementar el detector de clics en Java y Kotlin.

En Java:

 view.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { Toast.makeText(v.getContext(), "Clicked on view", Toast.LENGTH_SHORT).show(); } };

En Kotlin:

 view.setOnClickListener({ view -> toast("Click") })

¡Guau! ¡Solo una línea de código! Podemos ver que la expresión lambda está rodeada de llaves. Los parámetros se declaran primero y el cuerpo va después del signo -> . Con el detector de clics, no se especifica el tipo del parámetro de vista, ya que se puede inferir. El cuerpo es simplemente una llamada a la función toast() para mostrar el brindis, que proporciona Kotlin.

Además, si no se utilizan parámetros, podemos omitirlos:

 view.setOnClickListener({ toast("Click") })

Kotlin tiene bibliotecas Java optimizadas, y cualquier función que reciba una interfaz con un método para un argumento se puede llamar con un argumento de función (en lugar de Interfaz).

Además, si la función es el último parámetro, se puede sacar de los paréntesis:

 view.setOnClickListener() { toast("Click") }

Finalmente, si la función tiene solo un parámetro que es una función, se pueden omitir los paréntesis:

 view.setOnClickListener { toast("Click") }

Para obtener más información, consulta el libro Kotlin para desarrolladores de Android de Antonio Leiva y la documentación oficial.

Funciones de extensión

Kotlin, similar a C#, brinda la capacidad de ampliar las clases existentes con nuevas funciones mediante el uso de funciones de extensión. Por ejemplo, un método de extensión que calcularía el hash MD5 de un String :

 fun String.md5(): ByteArray { val digester = MessageDigest.getInstance("MD5") digester.update(this.toByteArray(Charset.defaultCharset())) return digester.digest() }

Tenga en cuenta que el nombre de la función está precedido por el nombre de la clase extendida (en este caso, String ) y que la instancia de la clase extendida está disponible a través de this palabra clave.

Las funciones de extensión son el equivalente de las funciones de utilidad de Java. La función de ejemplo en Java se vería así:

 public static int toNumber(String instance) { return Integer.valueOf(instance); }

La función de ejemplo debe colocarse en una clase de utilidad. Lo que eso significa es que las funciones de extensión no modifican la clase extendida original, pero son una forma conveniente de escribir métodos de utilidad.

Característica #5: Seguridad nula

Una de las cosas que más te preocupan en Java es probablemente NullPointerException . La seguridad nula es una función que se ha integrado en el lenguaje Kotlin y está tan implícita que, por lo general, no tendrás que preocuparte. La documentación oficial establece que las únicas causas posibles de NullPointerExceptions son:

  • Una llamada explícita para lanzar NullPointerException .
  • Usando el !! operador (que explicaré más adelante).
  • Código Java externo.
  • Si se accede a la propiedad lateinit en el constructor antes de que se inicialice, se generará una UninitializedPropertyAccessException .

De forma predeterminada, todas las variables y propiedades en Kotlin se consideran non-null (no pueden contener un valor null ) si no se declaran explícitamente como anulables. Como ya se mencionó, para definir una variable que acepte un valor null , se debe agregar un signo de interrogación después del tipo. Por ejemplo:

 val number: Int? = null

Sin embargo, tenga en cuenta que el siguiente código no se compilará:

 val number: Int? = null number.toString()

Esto se debe a que el compilador realiza comprobaciones null . Para compilar, se debe agregar una verificación null :

 val number: Int? = null if(number != null) { number.toString(); }

Este código se compilará con éxito. Lo que Kotlin hace en segundo plano, en este caso, es que el number se vuelve nun-null (¿ Int en lugar de Int? ) dentro del bloque if.

La verificación null se puede simplificar utilizando el operador de llamada segura ( ?. ):

 val number: Int? = null number?.toString()

La segunda línea se ejecutará solo si el número no es null . Incluso puedes usar el famoso operador de Elvis ( ?: :

 val number Int? = null val stringNumber = number?.toString() ?: "Number is null"

Si la expresión a la izquierda de ?: no es null , se evalúa y se devuelve. De lo contrario, se devuelve el resultado de la expresión de la derecha. Otra cosa interesante es que puedes usar throw o return en el lado derecho del operador de Elvis, ya que son expresiones en Kotlin. Por ejemplo:

 fun sendMailToUser(user: User) { val email = user?.email ?: throw new IllegalArgumentException("User email is null") //... }

Los !! Operador

Si desea que se genere una NullPointerException de la misma manera que en Java, puede hacerlo con el !! operador. El siguiente código arrojará una NullPointerException :

 val number: Int? = null number!!.toString()

Fundición

Casting realizado mediante el uso de una palabra clave as :

 val x: String = y as String

Esto se considera una conversión "insegura", ya que generará ClassCastException si la conversión no es posible, como lo hace Java. Hay un operador de conversión "seguro" que devuelve el valor null en lugar de lanzar una excepción:

 val x: String = y as? String

Para obtener más detalles sobre la conversión, consulte la sección Type Casts y Casts de la documentación oficial, y para obtener más detalles sobre la seguridad null , consulte la sección Seguridad nula.

propiedades lateinit

Existe un caso en el que el uso de propiedades lateinit puede causar una excepción similar a NullPointerException . Considere la siguiente clase:

 class InitTest { lateinit var s: String; init { val len = this.s.length } }

Este código se compilará sin previo aviso. Sin embargo, tan pronto como se crea una instancia de TestClass , se lanzará una UninitializedPropertyAccessException porque se accede a la propiedad s antes de que se inicialice.

Característica #6: Función with()

La función with() es útil y viene con la biblioteca estándar de Kotlin. Se puede usar para ahorrar algo de escritura si necesita acceder a muchas propiedades de un objeto. Por ejemplo:

 with(helloWorldTextView) { text = "Hello World!" visibility = View.VISIBLE }

Recibe un objeto y una función de extensión como parámetros. El bloque de código (entre llaves) es una expresión lambda para la función de extensión del objeto especificado como primer parámetro.

Característica #7: Sobrecarga del operador

Con Kotlin, se pueden proporcionar implementaciones personalizadas para un conjunto predefinido de operadores. Para implementar un operador, se debe proporcionar una función miembro o una función de extensión con el nombre dado.

Por ejemplo, para implementar el operador de multiplicación, se debe proporcionar una función miembro o función de extensión, con el nombre times(argument) :

 operator fun String.times(b: Int): String { val buffer = StringBuffer() for (i in 1..b) { buffer.append(this) } return buffer.toString() }

El ejemplo anterior muestra una implementación del operador binario * en String . Por ejemplo, la siguiente expresión asignará el valor "TestTestTestTest" a una variable newString :

 val newString = "Test" * 4

Dado que se pueden usar funciones de extensión, significa que se puede cambiar el comportamiento predeterminado de los operadores para todos los objetos. Esta es una espada de doble filo y debe usarse con precaución. Para obtener una lista de nombres de funciones para todos los operadores que se pueden sobrecargar, consulte la documentación oficial.

Otra gran diferencia con respecto a Java son los operadores == y != . Operador == se traduce a:

 a?.equals(b) ?: b === null

Mientras que el operador != se traduce a:

 !(a?.equals(b) ?:

Lo que eso significa es que usar == no realiza una verificación de identidad como en Java (compárese si las instancias de un objeto son iguales), sino que se comporta de la misma manera que el método equals() junto con las verificaciones null .

Para realizar una verificación de identidad, se deben usar los operadores === y !== en Kotlin.

Característica #8: Propiedades delegadas

Ciertas propiedades comparten algunos comportamientos comunes. Por ejemplo:

  • Propiedades con inicialización diferida que se inicializan en el primer acceso.
  • Propiedades que implementan Observable en el patrón Observer.
  • Propiedades que se almacenan en un mapa en lugar de campos separados.

Para facilitar la implementación de casos como este, Kotlin admite propiedades delegadas :

 class SomeClass { var p: String by Delegate() }

Esto significa que las funciones getter y setter para la propiedad p son manejadas por una instancia de otra clase, Delegate .

Un ejemplo de un delegado para la propiedad String :

 class Delegate { operator fun getValue(thisRef: Any?, property: KProperty<*>): String { return "$thisRef, thank you for delegating '${property.name}' to me!" } operator fun setValue(thisRef: Any?, property: KProperty<*>, value: String) { println("$value has been assigned to '${property.name} in $thisRef.'") } }

El ejemplo anterior imprime un mensaje cuando se asigna o lee una propiedad.

Se pueden crear delegados para propiedades mutables ( var ) y de solo lectura ( val ).

Para una propiedad de solo lectura, se debe implementar el método getValue . Toma dos parámetros (tomados de la documentación oficial):

  • receptor: debe ser el mismo o un supertipo del propietario de la propiedad (para propiedades de extensión, es el tipo que se extiende).
  • metadatos: debe ser del tipo KProperty<*> o su supertipo.

Esta función debe devolver el mismo tipo que la propiedad, o su subtipo.

Para una propiedad mutable, un delegado debe proporcionar adicionalmente una función llamada setValue que tome los siguientes parámetros:

  • receptor - igual que para getValue() .
  • metadatos - igual que para getValue() .
  • nuevo valor: debe ser del mismo tipo que una propiedad o su supertipo.

Hay algunos delegados estándar que vienen con Kotlin que cubren las situaciones más comunes:

  • Perezoso
  • Observable
  • vetable

Perezoso

Lazy es un delegado estándar que toma una expresión lambda como parámetro. La expresión lambda pasada se ejecuta la primera vez que se llama al método getValue() .

De forma predeterminada, la evaluación de las propiedades perezosas está sincronizada. Si no le preocupan los subprocesos múltiples, puede usar lazy(LazyThreadSafetyMode.NONE) { … } para obtener un rendimiento adicional.

Observable

El Delegates.observable() es para propiedades que deberían comportarse como Observables en el patrón Observer. Acepta dos parámetros, el valor inicial y una función que tiene tres argumentos (propiedad, valor antiguo y valor nuevo).

La expresión lambda dada se ejecutará cada vez que se llame al método setValue() :

 class User { var email: String by Delegates.observable("") { prop, old, new -> //handle the change from old to new value } }

vetable

Este delegado estándar es un tipo especial de Observable que le permite decidir si se almacenará o no un nuevo valor asignado a una propiedad. Se puede utilizar para comprobar algunas condiciones antes de asignar un valor. Al igual que Delegates.observable() , acepta dos parámetros: el valor inicial y una función.

La diferencia es que la función devuelve un valor booleano. Si devuelve true , el nuevo valor asignado a la propiedad se almacenará o se descartará.

 var positiveNumber = Delegates.vetoable(0) { d, old, new -> new >= 0 }

El ejemplo dado almacenará solo números positivos que se asignan a la propiedad.

Para más detalles, consulta la documentación oficial.

Característica #9: Asignación de un objeto a un mapa

Un caso de uso común es almacenar valores de las propiedades dentro de un mapa. Esto sucede a menudo en aplicaciones que funcionan con API RESTful y analizan objetos JSON. En este caso, una instancia de mapa se puede usar como delegado para una propiedad delegada. Un ejemplo de la documentación oficial:

 class User(val map: Map<String, Any?>) { val name: String by map val age: Int by map }

En este ejemplo, User tiene un constructor principal que toma un mapa. Las dos propiedades tomarán los valores del mapa que se asignan bajo claves que son iguales a los nombres de propiedad:

 val user = User(mapOf( "name" to "John Doe", "age" to 25 ))

A la propiedad de nombre de la nueva instancia de usuario se le asignará el valor de "John Doe" y a la propiedad de edad el valor de 25.

Esto también funciona para propiedades var en combinación con MutableMap :

 class MutableUser(val map: MutableMap<String, Any?>) { var name: String by map var age: Int by map }

Característica #10: Colecciones y Operaciones Funcionales

Con la compatibilidad con lambdas en Kotlin, las colecciones pueden llevarse a un nuevo nivel.

En primer lugar, Kotlin distingue entre colecciones mutables e inmutables. Por ejemplo, hay dos versiones de la interfaz iterable :

  • Iterable
  • MutableIterable

Lo mismo ocurre con las interfaces Collection , List , Set y Map .

Por ejemplo, esta operación any devuelve true si al menos un elemento coincide con el predicado dado:

 val list = listOf(1, 2, 3, 4, 5, 6) assertTrue(list.any { it % 2 == 0 })

Para obtener una lista extensa de las operaciones funcionales que se pueden realizar en las colecciones, consulte esta publicación de blog.

Conclusión

Acabamos de arañar la superficie de lo que ofrece Kotlin. Para aquellos interesados ​​en seguir leyendo y aprender más, consulte:

  • Blog y libro Kotlin de Antonio Leiva.
  • Documentación oficial y tutoriales de JetBrains.

En resumen, Kotlin le ofrece la posibilidad de ahorrar tiempo al escribir aplicaciones nativas de Android utilizando una sintaxis intuitiva y concisa. Todavía es un lenguaje de programación joven, pero en mi opinión, ahora es lo suficientemente estable como para usarse para crear aplicaciones de producción.

Los beneficios de usar Kotlin:

  • El soporte de Android Studio es perfecto y excelente.
  • Es fácil convertir un proyecto Java existente a Kotlin.
  • El código Java y Kotlin pueden coexistir en el mismo proyecto.
  • No hay sobrecarga de velocidad en la aplicación.

Las desventajas:

  • Kotlin agregará sus bibliotecas al .apk generado, por lo que el tamaño final del .apk será aproximadamente 300 KB más grande.
  • Si se abusa, la sobrecarga del operador puede generar código ilegible.
  • IDE y Autocompletar se comportan un poco más lentos cuando se trabaja con Kotlin que con proyectos Android de Java puro.
  • Los tiempos de compilación pueden ser un poco más largos.