En este tema, aprenderemos cómo integrar APIs REST en nuestras aplicaciones Flutter para obtener y enviar datos a servidores remotos. Este es un aspecto crucial del desarrollo de aplicaciones modernas, ya que permite que nuestras aplicaciones interactúen con servicios web y bases de datos en la nube.
Objetivos de Aprendizaje
- Comprender qué es una API REST y cómo funciona.
- Configurar una solicitud HTTP en Flutter.
- Manejar respuestas de API y errores.
- Enviar datos a un servidor mediante una API REST.
¿Qué es una API REST?
Una API REST (Representational State Transfer) es un conjunto de reglas que permiten la comunicación entre sistemas a través de HTTP. Las APIs RESTful utilizan métodos HTTP estándar como GET, POST, PUT y DELETE para realizar operaciones CRUD (Crear, Leer, Actualizar, Eliminar).
Métodos HTTP Comunes
Método | Descripción |
---|---|
GET | Recupera datos del servidor. |
POST | Envía datos al servidor para crear un nuevo recurso. |
PUT | Actualiza un recurso existente en el servidor. |
DELETE | Elimina un recurso del servidor. |
Configuración de una Solicitud HTTP en Flutter
Para realizar solicitudes HTTP en Flutter, utilizaremos el paquete http
. Asegúrate de agregarlo a tu archivo pubspec.yaml
:
Luego, importa el paquete en tu archivo Dart:
Realizando una Solicitud GET
Vamos a realizar una solicitud GET para obtener datos de una API pública. Por ejemplo, usaremos la API de JSONPlaceholder para obtener una lista de posts.
Future<void> fetchPosts() async { final response = await http.get(Uri.parse('https://jsonplaceholder.typicode.com/posts')); if (response.statusCode == 200) { List<dynamic> posts = jsonDecode(response.body); print(posts); } else { throw Exception('Failed to load posts'); } }
Explicación del Código
- Importaciones: Importamos el paquete
http
ydart:convert
para manejar las solicitudes HTTP y la conversión de JSON. - Solicitud GET: Utilizamos
http.get
para realizar una solicitud GET a la URL de la API. - Manejo de Respuesta: Verificamos si el
statusCode
de la respuesta es 200 (OK). Si es así, decodificamos el cuerpo de la respuesta JSON y lo imprimimos. Si no, lanzamos una excepción.
Enviando Datos con una Solicitud POST
Para enviar datos a un servidor, utilizamos el método POST. Vamos a enviar un nuevo post a la API de JSONPlaceholder.
Future<void> createPost(String title, String body) async { final response = await http.post( Uri.parse('https://jsonplaceholder.typicode.com/posts'), headers: <String, String>{ 'Content-Type': 'application/json; charset=UTF-8', }, body: jsonEncode(<String, String>{ 'title': title, 'body': body, 'userId': '1', }), ); if (response.statusCode == 201) { print('Post created: ${response.body}'); } else { throw Exception('Failed to create post'); } }
Explicación del Código
- Solicitud POST: Utilizamos
http.post
para enviar una solicitud POST a la URL de la API. - Encabezados: Especificamos los encabezados de la solicitud, indicando que el contenido es JSON.
- Cuerpo de la Solicitud: Codificamos el cuerpo de la solicitud en JSON.
- Manejo de Respuesta: Verificamos si el
statusCode
de la respuesta es 201 (Created). Si es así, imprimimos la respuesta. Si no, lanzamos una excepción.
Manejo de Errores
Es importante manejar los errores que pueden ocurrir durante las solicitudes HTTP. Aquí hay un ejemplo de cómo hacerlo:
Future<void> fetchPosts() async { try { final response = await http.get(Uri.parse('https://jsonplaceholder.typicode.com/posts')); if (response.statusCode == 200) { List<dynamic> posts = jsonDecode(response.body); print(posts); } else { throw Exception('Failed to load posts'); } } catch (e) { print('Error: $e'); } }
Explicación del Código
- Bloque try-catch: Envolvemos la solicitud HTTP en un bloque
try-catch
para capturar cualquier excepción que pueda ocurrir. - Manejo de Excepciones: Si ocurre una excepción, la capturamos y la imprimimos.
Ejercicio Práctico
Ejercicio
- Crea una aplicación Flutter que obtenga una lista de usuarios de la API de JSONPlaceholder (
https://jsonplaceholder.typicode.com/users
) y los muestre en una lista. - Agrega una funcionalidad para crear un nuevo usuario utilizando una solicitud POST.
Solución
Paso 1: Crear la Función para Obtener Usuarios
Future<List<dynamic>> fetchUsers() async { final response = await http.get(Uri.parse('https://jsonplaceholder.typicode.com/users')); if (response.statusCode == 200) { return jsonDecode(response.body); } else { throw Exception('Failed to load users'); } }
Paso 2: Mostrar Usuarios en una Lista
class UserList extends StatelessWidget { @override Widget build(BuildContext context) { return FutureBuilder<List<dynamic>>( future: fetchUsers(), builder: (context, snapshot) { if (snapshot.connectionState == ConnectionState.waiting) { return CircularProgressIndicator(); } else if (snapshot.hasError) { return Text('Error: ${snapshot.error}'); } else { return ListView.builder( itemCount: snapshot.data?.length ?? 0, itemBuilder: (context, index) { return ListTile( title: Text(snapshot.data[index]['name']), subtitle: Text(snapshot.data[index]['email']), ); }, ); } }, ); } }
Paso 3: Crear la Función para Enviar Datos
Future<void> createUser(String name, String email) async { final response = await http.post( Uri.parse('https://jsonplaceholder.typicode.com/users'), headers: <String, String>{ 'Content-Type': 'application/json; charset=UTF-8', }, body: jsonEncode(<String, String>{ 'name': name, 'email': email, }), ); if (response.statusCode == 201) { print('User created: ${response.body}'); } else { throw Exception('Failed to create user'); } }
Resumen
En esta lección, hemos aprendido cómo integrar APIs REST en nuestras aplicaciones Flutter utilizando el paquete http
. Hemos cubierto cómo realizar solicitudes GET y POST, manejar respuestas y errores, y enviar datos al servidor. Estos conceptos son fundamentales para construir aplicaciones que interactúan con servicios web y bases de datos en la nube.
En el próximo módulo, exploraremos cómo manejar la persistencia y el almacenamiento de datos en Flutter.
Curso de Desarrollo con Flutter
Módulo 1: Introducción a Flutter
- ¿Qué es Flutter?
- Configuración del Entorno de Desarrollo
- Entendiendo la Arquitectura de Flutter
- Creando Tu Primera App con Flutter
Módulo 2: Conceptos Básicos de Programación en Dart
- Introducción a Dart
- Variables y Tipos de Datos
- Sentencias de Control de Flujo
- Funciones y Métodos
- Programación Orientada a Objetos en Dart
Módulo 3: Widgets en Flutter
- Introducción a los Widgets
- Widgets Stateless vs Stateful
- Widgets Básicos
- Widgets de Diseño
- Widgets de Entrada y Formularios
Módulo 4: Gestión de Estado
Módulo 5: Navegación y Enrutamiento
- Introducción a la Navegación
- Navegación Básica
- Rutas Nombradas
- Pasando Datos Entre Pantallas
- Deep Linking
Módulo 6: Redes y APIs
- Obteniendo Datos de Internet
- Parseo de Datos JSON
- Manejo de Errores de Red
- Usando APIs REST
- Integración con GraphQL
Módulo 7: Persistencia y Almacenamiento
- Introducción a la Persistencia
- Preferencias Compartidas
- Almacenamiento de Archivos
- Base de Datos SQLite
- Usando Hive para Almacenamiento Local
Módulo 8: Conceptos Avanzados de Flutter
- Animaciones en Flutter
- Custom Paint y Canvas
- Canales de Plataforma
- Isolates y Concurrencia
- Optimización de Rendimiento
Módulo 9: Pruebas y Depuración
- Introducción a las Pruebas
- Pruebas Unitarias
- Pruebas de Widgets
- Pruebas de Integración
- Técnicas de Depuración
Módulo 10: Despliegue y Mantenimiento
- Preparación para el Lanzamiento
- Construcción para iOS
- Construcción para Android
- Integración Continua/Despliegue Continuo (CI/CD)
- Mantenimiento y Actualización de Tu App