Integración de OpenFood API en Android con Retrofit y Kotlin
Clase 11 de 20 • Curso de Patrones MVVM en Android
Resumen
En el mundo del desarrollo de aplicaciones, consumir APIs de manera eficiente es esencial para aprovechar al máximo los datos disponibles en internet. En esta clase, exploramos cómo utilizar la API OpenFood en una aplicación Android, empleando herramientas poderosas como Retrofit y Kotlin. Veamos cómo se integra una API REST y cómo se organiza su estructura para obtener información valiosa sobre alimentos.
¿Qué es un API REST y cómo funciona?
Un API REST es una interfaz que permite conectar nuestra aplicación con servidores en internet. A través de métodos HTTP como GET, PUT, DELETE o POST, puedes interactuar con servicios web para enviar y recibir datos. Dichos datos se modelan en estructuras JSON que luego se transforman a objetos que nuestro aplicativo puede manejar. Así, entender la diferencia entre un objeto y una colección en un API REST es crucial. Un objeto es una entidad única con propiedades específicas, mientras que una colección es un conjunto de objetos ordenados.
¿Cómo modelar una API con Retrofit?
Para consumir una API en una aplicación Android, Retrofit es una de las bibliotecas más populares gracias a su eficacia para manejar respuestas JSON con Kotlin. Los pasos para configurar Retrofit implican:
-
Crear paquetes para la estructuración de datos: se inicia con un paquete de data, dentro del cual se ubican los Data Transfer Objects (DTOs). Estos DTOs convertirán las respuestas JSON a objetos Kotlin.
-
Definir clases de datos: usar anotaciones de JSON para mapear las claves del JSON a propiedades de objetos. Por ejemplo, una clase
Nutriments
podría incluir propiedades comocarbohidratos
oproteínas
usando tipos de datos comoDouble
.
@JsonClass(generateAdapter = true)
data class Nutriments(
@Json(name = "carbohydrates_100g") val carbohydrates100g: Double,
@Json(name = "proteins_100g") val proteins100g: Double,
// Otros atributos...
)
- Conectar con el API mediante Retrofit: crear interfaces que definan los métodos de conexión con el API. Aquí, se especifican las rutas y los parámetros necesarios para hacer las llamadas respectivas.
interface OpenFoodAPI {
@GET("cgi/search.pl")
suspend fun searchFood(
@Query("search_terms") query: String,
@Query("page") page: Int,
@Query("page_size") pageSize: Int
): SearchDTO
}
¿Cómo estructurar capas de datos y dominio?
Para una segregación clara del código, se utilizan capas separadas:
- Capa de Datos: aquí se definen las implementaciones necesarias para consumir el API. Asegúrate de manejar excepciones usando
try-catch
para manejar posibles fallas en las conexiones.
val searchDTO = api.searchFood(query, page, pageSize)
return Result.success(
searchDTO.products.mapNotNull { it.toTrackableFood() }
)
- Capa de Dominio: incluye los modelos más abstractos usados en las interfaces de usuario. Aquí se crean casos de uso, como búsqueda de alimentos, que transforman y filtran las respuestas del API para presentarlas de manera accesible y estética al usuario.
data class TrackableFood(
val name: String,
val imageUrl: String?,
val caloriesPer100g: Int,
// Otros atributos...
)
¿Inyección de dependencias para escalabilidad?
Para construir aplicaciones escalables y fáciles de mantener, la inyección de dependencias es clave. El uso de librerías como Dagger facilita la gestión de dependencias:
- Módulos de Inyección: definen y proveen instancias de clases necesarias, como Retrofit y los repositorios de datos. Esto asegura que las instancias se reutilicen eficientemente.
@Module
@InstallIn(SingletonComponent::class)
object TrackerDataModule {
@Provides
fun provideOpenFoodAPI(client: OkHttpClient): OpenFoodAPI {
return Retrofit.Builder()
.baseUrl(OpenFoodAPI.BASE_URL)
.client(client)
.build()
.create(OpenFoodAPI::class.java)
}
@Provides
fun provideOkHttpClient(): OkHttpClient {
return OkHttpClient.Builder()
.addInterceptor(HttpLoggingInterceptor().apply {
setLevel(HttpLoggingInterceptor.Level.BODY)
})
.build()
}
}
Empleando estas técnicas y estructuras, puedes optimizar tu aplicación para un consumo eficiente de APIs. La clave está en mantener un código limpio y estructurado, garantizando que cada componente cumple con su función específica mientras interactúa de manera armoniosa con el resto del sistema. ¡Sigue explorando y mejorando tus habilidades para crear soluciones más poderosas y efectivas!