Cómo usar Retrofit en android con Kotlin (KDA 21)
Antonio Leiva

Este es sólo un ejemplo más de que en Kotlin podemos seguir usando las mismas librerías que siempre hemos utilizado en Java para Android.

Retrofit es una librería que simplifica muchísimo la generación de peticiones contra un API, y en este caso te voy a enseñar cómo integrarla con algunas peticiones del API de LastFM. Puedes ver el código completo funcionando en el repositorio de Bandhook Kotlin.

¿Te gustaría comenzar hoy a dar el siguiente paso? Te recomiendo que entres en mi training gratuito aquí

Retrofit 2 en Kotlin

El código en Kotlin va a ser muy parecido a lo que usaríamos en Java. Veremos más en detalle cuáles son algunas de sus diferencias, pero verás que todo es bastante sencillo e intuitivo.

Y también crearemos alguna función de extensión muy útil, ya veras.

Configuración del build.gradle

Tampoco entraré mucho en esto, pero puedes añadir las siguientes instrucciones al build.gradle:

compile "com.squareup.okhttp3:okhttp:$okhttpVersion"
compile "com.squareup.okhttp3:logging-interceptor:$okhttpVersion"

compile ("com.squareup.retrofit2:retrofit:$retrofitVersion"){
    // exclude Retrofit’s OkHttp peer-dependency module and define your own module import
    exclude module: 'okhttp'
}
compile "com.squareup.retrofit2:converter-gson:$retrofitVersion"

Las primeras dependencias incluyen la última versión de OkHttp y un interceptor que sirve para hacer logging, que puede ser útil para depurar.

Las siguientes añaden Retrofit (excluyendo OkHttp, para que tengamos control sobre la versión que usamos), y el conversor de Gson para convertir las peticiones a clases.

Crea la interfaz de comunicación

Esta es la parte neurálgica de Retrofit. Es donde se especifica la estructura de las peticiones, que tendrá que coincidir con la de la API:

interface LastFmService {

    @GET("/2.0/?method=artist.search")
    fun searchArtist(@Query("artist") artist: String): Call

    @GET("/2.0/?method=artist.getinfo")
    fun requestArtistInfo(@Query("mbid") id: String, @Query("lang") language: String): Call

    @GET("/2.0/?method=artist.gettopalbums")
    fun requestAlbums(@Query("mbid") id: String, @Query("artist") artist: String): Call;

    @GET("/2.0/?method=artist.getsimilar")
    fun requestSimilar(@Query("mbid") id: String): Call

    @GET("/2.0/?method=album.getInfo")
    fun requestAlbum(@Query("mbid") id: String): Call
}

No tiene mucha historia. Se identifica el tipo de la petición con la notación, y luego los parámetros de la petición como argumentos de la función.

En Retrofit 2, necesitamos devolver objetos del tipo Call.

Inicialización del servicio de comunicación

Primero puedes inicializar el cliente de OkHttp de la siguiente forma:

val client = OkHttpClient().newBuilder()
    .cache(cache)
    .addInterceptor(LastFmRequestInterceptor(apiKey, cacheDuration))
    .addInterceptor(HttpLoggingInterceptor().apply {
        level = if (BuildConfig.DEBUG) Level.BODY else Level.NONE
    })
    .build()
}

Aquí podemos ver la utilización de la función, apply, que nos ayudará a inicializar el interceptor al estilo de un builder, sin necesidad de que la clase implemente ningún tipo de builder.

El LastFmRequestInterceptor no tiene nada muy destacable, pero le puedes echar un ojo en Github. Nada especial tampoco en la creación del servicio:

val retrofit = Retrofit.Builder()
        .baseUrl("http://ws.audioscrobbler.com")
        .client(client)
        .addConverterFactory(GsonConverterFactory.create())
        .build()

val lastFmService = retrofit.create(LastFmService::class.java)

Haz tu primera petición

Debido a la necesidad de las Call en Retrofit 2, se vuelve un poco más tedioso el código:

val call = lastFmService.requestAlbums(mbid, name)
val result = call.execute().body()
val albums = AlbumMapper().transform(result.topAlbums.albums)

Sin embargo, gracias a las funciones de extensión, nos podemos crear una función sobre Call que nos recupere los valores, de esta forma:

val albums = lastFmService.requestAlbums(mbid, name).unwrapCall { 
    AlbumMapper().transform(topAlbums.albums)
}

Mucho más sencillo, ¿verdad?

¿Cuál es la forma de unwrapCall?

inline fun <T, U> Call.unwrapCall(f: T.() -> U): U = execute().body().f()

Es una función que extiende a Call, y que lo que hace es ejecutar la petición, recuperar el body, y hacer que éste (que será de tipo U) ejecute la función f().

En el ejemplo de arriba T es LastFmResponse y U es List.

Conclusión

Con este ejemplo te quería demostrar una vez más que cualquiera de las librerías Java que conoces puede ser utilizada en Kotlin sin problema.

También que, lejos de suponer una complicación, en la mayoría de los casos el lenguaje nos hará las cosas incluso más sencillas.

Anímate y vente al training gratuito, donde te contaré todo lo que necesitas para aprender a crear tus Apps Android en Kotlin desde cero. Descúbrelo todo sobre el lenguaje del futuro.

Quizá también te interese…

Kotlin 1.5.0 : Las 5 novedades que puedes empezar a usar hoy

Kotlin 1.5.0 : Las 5 novedades que puedes empezar a usar hoy

Kotlin 1.5.0 ya está aquí, y como siempre trae una serie de novedades que te van a interesar muchísimo. Cabe destacar que a partir de ahora, de acuerdo las nuevas versiones de Kotlin se lanzarán cada 6 meses, independientemente de las nuevas funcionalidades que...

¿Qué es Kotlin y para qué sirve?

¿Qué es Kotlin y para qué sirve?

Kotlin es un lenguaje de programación de código abierto creado por JetBrains que se ha popularizado gracias a que se puede utilizar para programar aplicaciones Android. Pero si has llegado hasta aquí pensando que Kotlin solo se puede usar en Android, lo que te voy a...

2 formas de recolectar Flows en la UI que SÍ funcionan

2 formas de recolectar Flows en la UI que SÍ funcionan

En la serie de artículos sobre Programación Reactiva con Flow hemos visto muchos conceptos, y hemos aprendido cómo aplicarlos al desarrollo Android. Pero hay algo que no hemos hecho del todo bien. Esto es la recolección de Flows desde la Activity (o el Fragment, en...

2 Comentarios

  1. neoranga55

    Lo primero gracias por la serie de artículos sobre Kotlin, es muy útil y la estoy disfrutando mucho como buen acompañamiento al libro de Kotlin.

    El ejemplo de apply es interesante pero muy abstracto para mi, ¿podrías por favor explicar un poco más cómo funciona y a qué métodos reemplaza?

    Responder
    • Antonio Leiva

      apply lo que hace es recibir en su función de extensión el objeto que llama a la función. Creo que queda más claro con una vista. Podrías hacer:


      val textView: TextView = TextView(this).apply {
      text = "Hello"
      textColor = Color.BLACK
      }

      Si dentro del apply haces “this”, te estás refiriendo al TextView. Esto te permite utilizar una estructura de builder para clases que no tienen un builder. El caso de este artículo es muy sencillo, pero te ahorras el tener que crear una variable antes, y llamar a interceptor.level = ... para luego asignárselo ahí. Lo puedes hacer de forma más compacta.

      Responder

Enviar un comentario

Los datos personales que proporciones a través de este formulario quedarán registrados en un fichero de Antonio Leiva Gordillo, con el fin de gestionar los comentarios que realizas en este blog. La legitimación se realiza a través del consentimiento de la parte interesada. Si no se acepta, no podrás comentar en este blog. Los datos que proporciona solo se utilizan para evitar el correo no deseado y no se usarán para nada más. Puede ejercer los derechos de acceso, rectificación, cancelación y oposición en contacto@devexperto.com.

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Acepto la política de privacidad *