Unidad 2: Desarrollo de
aplicaciones móviles
2.3 Servicios web: API REST
Danny Alfredo Torres Moran
Objetivos de la clase
Comprender y comparar los principales métodos de almacenamiento local en Flutter
(shared_preferences, hive, y sqflite) para seleccionar e implementar el más adecuado
según el tipo de datos, estructura y necesidades de persistencia de una aplicación móvil.
Comprender los principios del uso de internet móvil en aplicaciones Flutter, explorando
cómo realizar conexiones HTTP, consumir APIs, manejar asincronía y errores, optimizar la
experiencia del usuario móvil y aplicar buenas prácticas.
¿QUÉ ES UNA API?
¿CÓMO SE PRUEBA UNA API?
1
API significa Application Programming
Interface (Interfaz de Programación de 3 Antes de usarla en código, puedes probar una API con herramientas
visuales:
Aplicaciones).
Es una especie de "puente" que permite que Herramienta Para qué sirve
dos programas se comuniquen entre sí. Postman Hacer peticiones HTTP fácilmente y ver respuestas.
Insomnia Alternativa a Postman, más ligera.
Curl (en consola) Enviar solicitudes desde la terminal.
Navegador Puedes probar GET en URLs públicas.
En apps móviles (o web) usamos API REST Terminología usada:
para:
2 •Pedir información al servidor.
•Enviar datos al servidor. 4 API
Concepto Explicación rápida
Interfaz que permite que apps se comuniquen.
•Actualizar o eliminar datos. REST Estilo de arquitectura para crear APIs.
Endpoint Dirección específica para acceder a recursos.
Es como un mesero: tú (la app) haces un Método HTTP Indica si quieres leer, crear, actualizar o eliminar datos.
pedido (solicitud HTTP), y el mesero (la API) va JSON Formato de los datos enviados/recibidos.
a la cocina (servidor) y te trae la comida (datos Se hace con herramientas como Postman antes de
JSON). Prueba
programar.
¿CÓMO SE ESTRUCTURA UNA API REST?
Una API REST suele tener una URL base Códigos de respuesta (status codes):
1 (endpoint raíz):
Es la dirección principal del servidor, como:
4 Código Significado
[Link] 200 OK, todo bien
201 Creado con éxito
Recursos:
2
400 Error del cliente
Son los "objetos" que maneja la API, por ejemplo: 401 No autorizado
/recetas 404 No encontrado
/usuarios
500 Error del servidor
/pedidos
Datos en formato JSON (usualmente):
3 Métodos HTTP: Cada operación usa un método HTTP distinto:
Método ¿Para qué sirve? Ejemplo
5 Cuando haces una solicitud o recibes una
respuesta, los datos van en formato JSON:
GET Leer datos GET /recetas {
POST Crear nuevos datos POST /usuarios "id": 1,
"nombre": "Pizza",
PUT Actualizar datos PUT /usuarios/1 "ingredientes": ["queso", "masa", "tomate"]
DELETE Eliminar datos DELETE /usuarios/1 }
¿Qué significa "Servicios web: API REST"?
1. Servicios web: Son interfaces que permiten que diferentes
aplicaciones se comuniquen entre sí a través de Internet.
2. API REST (Representational State Transfer): Es un tipo de
servicio web que sigue un conjunto de reglas o principios
arquitectónicos. Usa generalmente HTTP para enviar y recibir datos
(como GET, POST, PUT, DELETE).
¿Para qué se usa en apps móviles?
En aplicaciones móviles, las API REST permiten:
[Link] datos desde un servidor remoto: por ejemplo, una app
de clima que obtiene la temperatura actual.
[Link] datos al servidor: como un formulario de registro o una En Flutter o Android/iOS nativo, se usa para:
imagen. •Mostrar contenido actualizado desde Internet.
[Link] o eliminar recursos en una base de datos remota. •Registrar usuarios o iniciar sesión.
[Link] contenido entre dispositivos (por ejemplo, notas, •Publicar información (comentarios, fotos, pedidos).
tareas, publicaciones, etc.). •Guardar y consultar datos en la nube.
¿Cómo lo aplico?
EJEMPLO:
Una app de recetas quiere mostrar recetas al usuario. La app no guarda todas las recetas localmente, sino que
las consulta a un servidor usando una API REST:
HTTP:
GET [Link]
Ese JSON lo usa la app para mostrar los datos en pantalla.
JSON:
[
{
"id": 1,
"titulo": "Torta de chocolate",
"ingredientes": ["harina", "cacao", "azúcar"]
}
]
Guía:
[Link]
[Link]
¿Cómo hacer peticiones HTTP en Flutter?
Flutter no consume APIs por sí solo. Se necesita un paquete (librería) para hacer las solicitudes:
Cómo hacer una solicitud básica (con http)
Principales paquetes: import 'package:http/[Link]' as http;
import 'dart:convert';
Paquete ¿Para qué sirve?
Future<void> getRecetas() async {
El más básico y fácil de final url = [Link]("[Link]
http
usar final response = await [Link](url);
Más potente: permite if ([Link] == 200) {
interceptores, manejo final data = [Link]([Link]);
dio
avanzado de errores, print(data); // aquí puedes usar los datos
cancelación, etc. } else {
print("Error: ${[Link]}");
}
}
¿Cómo usar los datos en la interfaz (UI)?
Debes combinar:
1. FutureBuilder → para mostrar los datos cuando estén listos.
2. Modelos (clases en Dart) → para mapear el JSON a objetos de Dart.
Ejemplo de modelo:
class Receta {
final int id;
final String titulo;
1. El JSON se convierte en objetos Dart con
Receta({required [Link], required [Link]}); métodos como fromJson().
2. Puedes usar herramientas automáticas como
factory [Link](Map<String, dynamic> json) [Link] o json_serializable si es
{ complejo.
return Receta(
id: json['id'],
titulo: json['titulo'],
);
}
}
¿Cómo manejar JSON (parseo y serialización)?
Crear una clase Dart
Cuando una API responde con datos en JSON, necesitas convertir ese texto a
class Receta {
objetos Dart para usarlo fácilmente.
final int id;
final String titulo;
¿Qué significa parsear?
final List<String> ingredientes;
Es transformar el JSON (que es texto) en un objeto de Dart que puedes manipular
como una clase común.
Receta({required [Link], required [Link], required
[Link]});
Ejemplo real de JSON recibido:
json
{ // Convertir JSON a objeto Dart
"id": 1, factory [Link](Map<String, dynamic> json) {
"titulo": "Torta de Chocolate", return Receta(
"ingredientes": ["harina", "huevos", "cacao"] id: json['id'],
} titulo: json['titulo'],
ingredientes: List<String>.from(json['ingredientes']),
);
}
// Convertir objeto Dart a JSON
Map<String, dynamic> toJson() {
Herramientas para automatizar: return {
1. [Link] pega un JSON y te genera la clase 'id': id,
Dart con fromJson y toJson. 'titulo': titulo,
2. json_serializable: paquete Flutter que genera 'ingredientes': ingredientes,
automáticamente ese código si usas anotaciones. };
}
}
Manejo de errores y estados
En apps reales, no todas las peticiones salen bien. Debes prever:
Tipos de errores comunes:
Solución básica con try/catch:
Tipo Ejemplo try {
Error de red No hay internet final response = await [Link](url);
if ([Link] == 200) {
Error de API Código 404, 500 final data = [Link]([Link]);
// trabajar con los datos
JSON mal formado Error al convertir } else {
throw Exception("Error de servidor: ${[Link]}");
Tiempo de espera El servidor no responde }
} catch (e) {
print("Error en la petición: $e");
}
En la interfaz:
Puedes usar FutureBuilder para mostrar distintos estados:
✓ loading → CircularProgressIndicator
✓ success → contenido cargado
✓ error → mensaje de error con botón de reintento
Autenticación
Algunas APIs privadas exigen autenticación como medida de seguridad.
Formas comunes de autenticación: Ejemplo de agregar token a la petición:
Tipo Qué hace final response = await [Link](
[Link]("[Link]
Después del login, la API te da un
Token JWT headers: {
token 'Authorization': 'Bearer TU_TOKEN_AQUI',
Usas una clave privada en los 'Content-Type': 'application/json',
API Key },
headers
);
Usado por Google, Facebook,
OAuth2
etc.
¿Dónde guardas el token?
Usa:
✓ shared_preferences: para almacenar el token de forma local.
✓ flutter_secure_storage: si necesitas más seguridad.
Buenas prácticas al trabajar con APIs en Flutter
Para que tu app sea escalable, ordenada y fácil de mantener:
Arquitectura recomendada:
1. Capa de modelos (models/[Link])
Define las clases que representan los datos.
2. Capa de servicios (services/api_service.dart)
class ApiService {
final String baseUrl = "[Link] 3. Capa de UI (screens/home_screen.dart)
La interfaz llama a los servicios para obtener datos.
Future<List<Receta>> obtenerRecetas() async {
final response = await
[Link]([Link]('$baseUrl/recetas'));
if ([Link] == 200) {
final List<dynamic> data = [Link]([Link]);
return [Link]((json) =>
[Link](json)).toList();
} else {
throw Exception('Error al cargar recetas');
}
}
}