En esta lección, aprenderemos cómo obtener datos de Internet en una aplicación Flutter. Este es un aspecto crucial para muchas aplicaciones modernas que dependen de datos en tiempo real o de servicios web para funcionar correctamente.
Objetivos de la Lección
- Entender cómo realizar solicitudes HTTP en Flutter.
- Aprender a manejar respuestas HTTP.
- Implementar la obtención de datos desde una API REST.
Requisitos Previos
- Conocimientos básicos de Dart y Flutter.
- Familiaridad con los conceptos de programación asíncrona.
Contenido
Introducción a las Solicitudes HTTP
HTTP (HyperText Transfer Protocol) es el protocolo utilizado para la comunicación entre clientes y servidores en la web. En Flutter, podemos realizar solicitudes HTTP para obtener datos de servidores remotos utilizando el paquete http
.
Configuración del Paquete HTTP
Para realizar solicitudes HTTP en Flutter, primero necesitamos agregar el paquete http
a nuestro proyecto.
- Abre el archivo
pubspec.yaml
de tu proyecto. - Agrega la dependencia
http
en la seccióndependencies
:
- Guarda el archivo y ejecuta
flutter pub get
para instalar la dependencia.
Realizando una Solicitud GET
Una solicitud GET se utiliza para obtener datos de un servidor. A continuación, se muestra cómo realizar una solicitud GET en Flutter:
import 'package:flutter/material.dart'; import 'package:http/http.dart' as http; void main() => runApp(MyApp()); class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( appBar: AppBar( title: Text('Obteniendo Datos de Internet'), ), body: Center( child: FutureBuilder( future: fetchData(), builder: (context, snapshot) { if (snapshot.connectionState == ConnectionState.waiting) { return CircularProgressIndicator(); } else if (snapshot.hasError) { return Text('Error: ${snapshot.error}'); } else { return Text('Datos: ${snapshot.data}'); } }, ), ), ), ); } Future<String> fetchData() async { final response = await http.get(Uri.parse('https://jsonplaceholder.typicode.com/posts/1')); if (response.statusCode == 200) { return response.body; } else { throw Exception('Error al obtener datos'); } } }
Explicación del Código
- Importaciones: Importamos los paquetes
flutter/material.dart
yhttp
. - Main Function: La función
main
ejecuta la aplicación. - MyApp Class: Definimos una clase
MyApp
que extiendeStatelessWidget
. - FutureBuilder: Utilizamos
FutureBuilder
para manejar la solicitud asíncrona y mostrar los datos obtenidos. - fetchData Function: Definimos una función
fetchData
que realiza una solicitud GET a una URL y devuelve los datos obtenidos.
Manejo de Respuestas HTTP
Es importante manejar adecuadamente las respuestas HTTP para asegurarnos de que nuestra aplicación funcione correctamente incluso cuando ocurren errores.
Ejemplo de Manejo de Errores
Future<String> fetchData() async { try { final response = await http.get(Uri.parse('https://jsonplaceholder.typicode.com/posts/1')); if (response.statusCode == 200) { return response.body; } else { throw Exception('Error al obtener datos: ${response.statusCode}'); } } catch (e) { throw Exception('Error de red: $e'); } }
En este ejemplo, utilizamos un bloque try-catch
para manejar posibles errores de red.
Ejemplo Práctico
Vamos a crear una aplicación que obtenga una lista de publicaciones desde una API y las muestre en una lista.
import 'package:flutter/material.dart'; import 'package:http/http.dart' as http; import 'dart:convert'; void main() => runApp(MyApp()); class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( appBar: AppBar( title: Text('Lista de Publicaciones'), ), body: PostsList(), ), ); } } class PostsList extends StatefulWidget { @override _PostsListState createState() => _PostsListState(); } class _PostsListState extends State<PostsList> { Future<List<Post>> fetchPosts() async { final response = await http.get(Uri.parse('https://jsonplaceholder.typicode.com/posts')); if (response.statusCode == 200) { List jsonResponse = json.decode(response.body); return jsonResponse.map((post) => Post.fromJson(post)).toList(); } else { throw Exception('Error al obtener publicaciones'); } } @override Widget build(BuildContext context) { return FutureBuilder<List<Post>>( future: fetchPosts(), 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, itemBuilder: (context, index) { return ListTile( title: Text(snapshot.data![index].title), subtitle: Text(snapshot.data![index].body), ); }, ); } }, ); } } class Post { final int id; final String title; final String body; Post({required this.id, required this.title, required this.body}); factory Post.fromJson(Map<String, dynamic> json) { return Post( id: json['id'], title: json['title'], body: json['body'], ); } }
Explicación del Código
- fetchPosts Function: Realiza una solicitud GET para obtener una lista de publicaciones y las convierte en una lista de objetos
Post
. - Post Class: Define una clase
Post
con un métodofromJson
para convertir JSON en un objetoPost
. - FutureBuilder: Utiliza
FutureBuilder
para manejar la solicitud asíncrona y mostrar la lista de publicaciones.
Ejercicio Práctico
Ejercicio
Crea una aplicación Flutter que obtenga una lista de usuarios desde la API https://jsonplaceholder.typicode.com/users
y los muestre en una lista. Cada elemento de la lista debe mostrar el nombre y el correo electrónico del usuario.
Solución
import 'package:flutter/material.dart'; import 'package:http/http.dart' as http; import 'dart:convert'; void main() => runApp(MyApp()); class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( appBar: AppBar( title: Text('Lista de Usuarios'), ), body: UsersList(), ), ); } } class UsersList extends StatefulWidget { @override _UsersListState createState() => _UsersListState(); } class _UsersListState extends State<UsersList> { Future<List<User>> fetchUsers() async { final response = await http.get(Uri.parse('https://jsonplaceholder.typicode.com/users')); if (response.statusCode == 200) { List jsonResponse = json.decode(response.body); return jsonResponse.map((user) => User.fromJson(user)).toList(); } else { throw Exception('Error al obtener usuarios'); } } @override Widget build(BuildContext context) { return FutureBuilder<List<User>>( 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, itemBuilder: (context, index) { return ListTile( title: Text(snapshot.data![index].name), subtitle: Text(snapshot.data![index].email), ); }, ); } }, ); } } class User { final int id; final String name; final String email; User({required this.id, required this.name, required this.email}); factory User.fromJson(Map<String, dynamic> json) { return User( id: json['id'], name: json['name'], email: json['email'], ); } }
Explicación del Código
- fetchUsers Function: Realiza una solicitud GET para obtener una lista de usuarios y las convierte en una lista de objetos
User
. - User Class: Define una clase
User
con un métodofromJson
para convertir JSON en un objetoUser
. - FutureBuilder: Utiliza
FutureBuilder
para manejar la solicitud asíncrona y mostrar la lista de usuarios.
Conclusión
En esta lección, hemos aprendido cómo obtener datos de Internet en una aplicación Flutter utilizando el paquete http
. Hemos cubierto cómo realizar solicitudes GET, manejar respuestas HTTP y mostrar los datos obtenidos en la interfaz de usuario. Además, hemos implementado un ejemplo práctico y un ejercicio para reforzar los conceptos aprendidos.
En la próxima lección, aprenderemos cómo parsear datos JSON obtenidos de una API.
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