Retrofit es una biblioteca de Android desarrollada por Square que facilita la implementación de peticiones HTTP en nuestras aplicaciones.
Esta biblioteca es muy popular y utilizada por desarrolladores de todo el mundo debido a su simplicidad y facilidad de uso.
En este artículo, veremos cómo utilizar Retrofit para crear una conexión a una API de películas y realizar operaciones CRUD (crear, leer, actualizar y eliminar) utilizando Kotlin como lenguaje de programación.
Para empezar, necesitamos agregar la dependencia de Retrofit y del adapter de Gson en nuestro archivo build.gradle
:
implementation 'com.squareup.retrofit2:retrofit:2.7.2' implementation 'com.squareup.retrofit2:converter-gson:2.4.0'
A continuación, creamos una interfaz que define los métodos que utilizaremos para realizar las operaciones CRUD en la API de películas. En este ejemplo, utilizaremos la API de The Movie Database (TMDb):
interface MovieAPI { // Método para crear una película @POST("movie") fun createMovie(@Body movie: Movie): Call<Movie> // Método para obtener todas las películas @GET("movie") fun getMovies(): Call<List<Movie>> // Método para obtener una película por su ID @GET("movie/{id}") fun getMovie(@Path("id") id: Int): Call<Movie> // Método para actualizar una película @PUT("movie/{id}") fun updateMovie(@Path("id") id: Int, @Body movie: Movie): Call<Movie> // Método para eliminar una película @DELETE("movie/{id}") fun deleteMovie(@Path("id") id: Int): Call<Void> }
En cada uno de estos métodos, especificamos el tipo de petición HTTP que utilizaremos (POST, GET, PUT o DELETE) y la ruta de la API donde se realizará la petición.
Además, en los métodos que reciben o envían una película, utilizamos la anotación @Body
para indicar que el cuerpo de la petición será el objeto de tipo Movie
.
Ahora, creamos una clase que implemente esta interfaz y que utilice Retrofit para realizar las peticiones HTTP:
class MovieService { // Instancia de Retrofit private val retrofit = Retrofit.Builder() .baseUrl("https://api.themoviedb.org/3/") .addConverterFactory(GsonConverterFactory.create()) .build() // Método para crear una película fun createMovie(movie: Movie) { movieAPI.createMovie(movie).enqueue(object : Callback<Movie> { override fun onResponse(call: Call<Movie>, response: Response<Movie>) { // Procesar respuesta exitosa } override fun onFailure(call: Call<Movie>, t: Throwable) { // Procesar error en la petición } }) } // Método para obtener todas las películas fun getMovies() { movieAPI.getMovies().enqueue(object : Callback<List<Movie>> { override fun onResponse(call: Call<List<Movie>>, response: Response<List<Movie>>) { // Procesar respuesta exitosa } override fun onFailure(call: Call<List<Movie>>, t: Throwable) { // Procesar error en la petición } }) } // Método para obtener una película por su ID fun getMovie(id: Int) { movieAPI.getMovie(id).enqueue(object : Callback<Movie> { override fun onResponse(call: Call<Movie>, response: Response<Movie>) { // Procesar respuesta exitosa } override fun onFailure(call: Call<Movie>, t: Throwable) { // Procesar error en la petición } }) } // Método para actualizar una película fun updateMovie(id: Int, movie: Movie) { movieAPI.updateMovie(id, movie).enqueue(object : Callback<Movie> { override fun onResponse(call: Call<Movie>, response: Response<Movie>) { // Procesar respuesta exitosa } override fun onFailure(call: Call<Movie>, t: Throwable) { // Procesar error en la petición } }) } // Método para eliminar una película fun deleteMovie(id: Int) { movieAPI.deleteMovie(id).enqueue(object : Callback<Void> { override fun onResponse(call: Call<Void>, response: Response<Void>) { // Procesar respuesta exitosa } override fun onFailure(call: Call<Void>, t: Throwable) { // Procesar error en la petición } }) } }
En esta clase, utilizamos Retrofit para crear una instancia de la interfaz MovieAPI
. Luego, en cada uno de los métodos, utilizamos esta instancia para realizar la petición correspondiente a la operación CRUD deseada. También utilizamos el método enqueue()
para ejecutar la petición en un hilo en segundo plano y recibir la respuesta en un callback.
Por último, en nuestro código podemos utilizar esta clase de la siguiente manera para realizar las operaciones CRUD en la API de películas:
val movieService = MovieService() // Crear una película val movie = Movie(...) movieService.createMovie(movie) // Obtener todas las películas movieService.getMovies() // Obtener una película por su ID val id = 1 movieService.getMovie(id) // Actualizar una película val updatedMovie = Movie(...) movieService.updateMovie(id, updatedMovie) // Eliminar una película movieService.deleteMovie(id)
Retrofit tiene soporte para corrutinas
Si utilizamos el soporte oficial de la librería Retrofit para corrutinas, el código cambia de la siguiente manera.
La interfaz MovieAPI
se modifica para crear funciones suspend
:
interface MovieAPI { // Método para crear una película @POST("movie") suspend fun createMovie(@Body movie: Movie): Movie // Método para obtener todas las películas @GET("movie") suspend fun getMovies(): List<Movie> // Método para obtener una película por su ID @GET("movie/{id}") suspend fun getMovie(@Path("id") id: Int): Movie // Método para actualizar una película @PUT("movie/{id}") suspend fun updateMovie(@Path("id") id: Int, @Body movie: Movie): Movie // Método para eliminar una película @DELETE("movie/{id}") suspend fun deleteMovie(@Path("id") id: Int): Void }
Y la clase MovieService
también tendrá métodos suspend
. Un ejemlo:
// Método para obtener todas las películas suspend fun getMovies(): List<Movie> { return movieAPI.getMovies() }
En nuestro código, podemos utilizar esta clase de la siguiente manera:
// Obtener todas las películas GlobalScope.launch(Dispatchers.Main) { val movies = movieService.getMovies() // Procesar lista de películas }
En resumen, Retrofit nos permite implementar peticiones HTTP de manera sencilla y eficiente en nuestras aplicaciones de Android utilizando Kotlin.
Con esta biblioteca, podemos conectar nuestra aplicación a cualquier API y realizar operaciones CRUD de manera rápida y sencilla.
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?
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.