Migrando Android de Java a Kotlin

Carlos Fernando Arboleda Garcés
6 min readJan 26, 2019

--

Imagen de Ruben Tejera. (https://rubentejera.com/por-que-usar-kotlin/)

Kotlin fue anunciado durante el Google I/O de 2017 como el lenguaje de programación oficial para desarrollar aplicaciones en Android y gracias a su capacidad de interoperar con Java, simplicidad y versatilidad, se está convirtiendo en el lenguaje más utilizado a la hora de programar en Android.

En este post te explico las características principales de Kotlin y algunas recomendaciones para que comiences a utilizarlo en tus proyectos sin morir en el intento.

Qué es Kotlin?

Kotlin es un lenguaje de programación de tipado estático que corre sobre la JVM (Java Virtual Machine), desarrollado por JetBrains (los mismos de IntelliJ y Android Studio), con capacidad para interoperar 100% con Java y además puede ser compilado a JavaScript.

Por qué migrar de Java a Kotlin?

Google estableció que Kotlin es el lenguaje oficial en Android y hoy en día no saber Kotlin te pone en desventaja en el mercado. Y además, tiene una sintaxis que te permite escribir código fuente hasta en un 40% menos de líneas que en Java. Y no puedo dejar de mencionar que la curva de aprendizaje es muy corta!

Desde hace unos meses comencé la migración de Java a Kotlin, principalmente motivado por la interoperabilidad con Java y la capacidad de controlar las variables nulas de una forma muy fácil, lo cual me permitiría migrar de forma progresiva; Pero me encontré con un universo de posibilidades…

Ahora vamos a ver algunas cosas cool de Kotlin!

Antes de comenzar en conveniente mencionar algunas particularidades de Kotlin:

  1. Todo objeto es un Any, el nodo raíz de la jerarquía.
  2. Para la definición de variables se utiliza val o var, y opcionalmente en frente y separado de : (dos puntos ) se define el tipo de dato.
  3. Se habla de funciones en lugar de métodos.
  4. Todo miembro de una clase (atributo o función) por defecto es público.
  5. Kotlin tiene su propio compilador (genera archivos .class).
  6. Toda expresión o función por defecto devuelve un Unit (es como void en java).

Ahora podemos controlar con más facilidad el famoso NullPointerException.

var a: String = "abc"
a = null // error de compilación

Para permitir nulos debemos declarar la variable como String?

var a: String? = "abc"
a = null // ok

Para acceder de forma segura a una variable que permite valores nulos, debemos usar la sintaxis .?

val l = a?.length // Si b es null el length también devolverá null

El operador !! permite convertir cualquier variable que soporte valores nulos a non-null al momento de accederla.

val l = a!!.length //Si b es null se lanzará un NullPointerException

El operador Elvis ?: es una contracción del famoso operador ternario que podemos usar en diferentes lenguajes.

int l = a != null ? a.length : -1 // Java
val l = a?.length ?: -1 // (Kotlin) Operador Elvis
  • Expresiones

En Kotlin los condicionales pueden retornar valores directamente.

val l = if(a != null) a.length else -1val l2 = when(a) {
null -> -1
else -> a.length
}

Nunca antes fue tan fácil definir clases (POJO), Kotlin hace el trabajo sucio por nosotros infiriendo el constructor de clase y las funciones get() / set(). Y heredando de Any las funciones equals() / hasCode() y copy()

// Definición
data class Usuario (
var nombre: String,
var edad: Int,
var ciudad: String
)
// Uso del data class
val unUsuario = Usuario("Carlos", 30, "Cali")
  • Parámetros nombrados y valores por defecto

Con Kotlin podemos olvidarnos de tener que sobrecargar constructores o funciones, ya que podemos declarar uno solo con todos los parámetros e invocarlo pasando solo los necesarios.

// Definición
data class Usuario (
var nombre: String,
var edad: Int,
val ciudad: String? = "Cali" // Definimos un valor por defecto
)
// Uso del data class
val usuario1 = Usuario("Carlos", 30)
val usuario2 = Usuario(nombre = "Carlos", edad = 30)
  • Template string

Para darle formato a una cadena (String) insertando valores dinámicos, en Java debemos utilizar String.format, mientras que en Kotlin podemos insertar los valores directamente en la cadena (String) o incluso utilizar expresiones.

val saludo = "Hola $nombre" //Variable
mTextView.setText("Hola $nombre, tu nombre tiene ${nombre.length} caracteres") // Expresión

También es posible usar cadenas de String de multiples líneas.

val info = """
Nombre: $nombre
Edad: $edad
Ciudad: $ciudad
"""
mTextView.setText(info)
  • Property sintax

Utilizando property sintax podemos omitir el uso explícito de las funciones set y get para simplemente asignar u obtener el valor de la variable como si se tratara de una variable pública.

// De manera convencional con los get y set
usuario.setNombre("Carlos Fernando")
mTextView.setText(usuario.getNombre())
// Con property sintax
usuario.nombre = "Carlos Fernando" // set
mTextView.text = usuario.nombre // get

El compilador detecta cuando verificamos el tipo de una variable y realiza el cast automático en caso de ser necesario.

fun demo(a: Any) {
if (a is String) {
mTextView.text = a // x es casteada a String automaticamente
}
}

Los lambdas son un herramienta potente de Kotlin que permite simplificar nuestro código al reducir el código necesario para declarar un callback y permitirnos pasar funciones como parámetros sin necesidad de crear interfaces.

when (c) {
true -> yes()
false -> {
not()
println("c es igual a false")
}
}
var contador = 0
boton.addClickListener {
contador++
mTextView.text = "Clicks $contador"
}
fun setOnClickListener(listener: (view: View) -> Unit) {}

Utilizando el plugin kotlin-android-extensions podremos acceder a las widgets o vistas de nuestros layouts directamente y sin necesidad de utilizar el muy conocido findViewById().

import kotlinx.android.synthetic.main.activity_main.*class MainActivity : Activity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)

// En lugar de findViewById<TextView>(R.id.textView)
mTextView.text = "Hola, mundo!"
}
}

Y qué pasa si ya tengo un proyecto Android en Java?

No te preocupes! Para esto Android Studio tiene un haz bajo la manga. Y es que tiene una opción que nos permite convertir el código Java a Kotlin en dos clics.

Una vez presionamos sobre la opción comenzará a convertir el archivo y después nos preguntará si también queremos actualizar las referencias a ese archivo.

IMPORTANTE: Como ya sabemos, Kotlin puede interoperar con Java así que al convertir los archivos debemos revisar minuciosamente cada invocación de métodos/funciones de Java a Kotlin, ya que si una variable es pasada como null a un método que la recibe como non-null obtendremos un error como el siguiente:

java.lang.IllegalArgumentException: Parameter specified as non-null is null: method kotlin.jvm.internal.Intrinsics.checkParameterIsNotNull

Veamos un ejemplo:

// Kotlin
class Mensaje {
//La forma correcta sería: fun mostrar(text: String?) {
fun mostrar(text: String) { //java.lang.IllegalArgumentException
//Hacer algo
}
}
// Java
Mensaje.mostrar(null);

Yo comencé la migración de una de mis aplicaciones hace un par de meses y actualmente he migrado un 40% a Kotlin obteniendo excelentes resultados. Logré mejorar la estabilidad de la aplicación al utilizar el null safety y simplificar el código fuente usando data class, lambdas,View Bindings y varias más.

Si vas a comenzar a migrar un proyecto, te recomiendo que lo hagas de forma progresiva a medida que va necesitando modificar el código existente. No frenes el proyecto hasta migrar todo porque será mucho más desgastante y además puede verse afectado el proyecto. Recuerda que Kotlin puede funcionar perfectamente con Java, así que puedes tomarlo con calma.

Te dejo los enlaces a dos cursos gratuitos de Udacity sobre Kotlin, el primero te permitirá conocer las todas características del lenguaje y el en segundo puedes ver más en detalle como migrar una aplicación de Java a Kotlin.

Si te ha gustado este post, recomiendalo 👏, comenta y comparte!

--

--

Carlos Fernando Arboleda Garcés

Senior Software Engineer at EPAM, Co-founder at Mobile Lab, Co-founder at La Manicurista, Former CTO at La Manicurista, Organizer at GDG Cali, GenAI enthusiast