En este tema, aprenderás cómo manejar errores de red en Flutter. La gestión adecuada de errores es crucial para crear aplicaciones robustas y ofrecer una buena experiencia de usuario. Cubriremos los siguientes puntos:

  1. Tipos Comunes de Errores de Red
  2. Manejo de Errores con try-catch
  3. Uso de Future y async-await para Manejo de Errores
  4. Manejo de Errores con Paquetes de Terceros
  5. Ejemplo Práctico
  6. Ejercicio Práctico

  1. Tipos Comunes de Errores de Red

Antes de manejar errores, es importante entender los tipos comunes de errores de red que puedes encontrar:

  • Errores de Conexión: Ocurren cuando no se puede establecer una conexión con el servidor.
  • Errores de Tiempo de Espera: Ocurren cuando la solicitud tarda demasiado en completarse.
  • Errores de Respuesta: Ocurren cuando el servidor responde con un código de estado HTTP que indica un error (por ejemplo, 404, 500).
  • Errores de Parseo: Ocurren cuando la respuesta del servidor no se puede convertir al formato esperado (por ejemplo, JSON malformado).

  1. Manejo de Errores con try-catch

En Dart, puedes usar bloques try-catch para manejar excepciones. Aquí hay un ejemplo básico:

import 'package:http/http.dart' as http;

Future<void> fetchData() async {
  try {
    final response = await http.get(Uri.parse('https://api.example.com/data'));
    if (response.statusCode == 200) {
      // Procesar la respuesta
      print('Datos recibidos: ${response.body}');
    } else {
      // Manejar errores de respuesta
      print('Error en la respuesta: ${response.statusCode}');
    }
  } catch (e) {
    // Manejar errores de conexión y otros
    print('Error de red: $e');
  }
}

  1. Uso de Future y async-await para Manejo de Errores

El uso de async-await facilita la lectura y el manejo de errores en código asíncrono. Aquí hay un ejemplo más detallado:

import 'dart:convert';
import 'package:http/http.dart' as http;

Future<void> fetchData() async {
  try {
    final response = await http.get(Uri.parse('https://api.example.com/data'));
    if (response.statusCode == 200) {
      final data = jsonDecode(response.body);
      // Procesar los datos
      print('Datos recibidos: $data');
    } else {
      // Manejar errores de respuesta
      print('Error en la respuesta: ${response.statusCode}');
    }
  } on http.ClientException catch (e) {
    // Manejar errores de conexión
    print('Error de conexión: $e');
  } catch (e) {
    // Manejar otros errores
    print('Error desconocido: $e');
  }
}

  1. Manejo de Errores con Paquetes de Terceros

Paquetes como dio ofrecen funcionalidades avanzadas para manejar errores de red. Aquí hay un ejemplo usando dio:

import 'package:dio/dio.dart';

Future<void> fetchData() async {
  final dio = Dio();

  try {
    final response = await dio.get('https://api.example.com/data');
    print('Datos recibidos: ${response.data}');
  } on DioError catch (e) {
    if (e.type == DioErrorType.connectTimeout) {
      print('Error de tiempo de espera');
    } else if (e.type == DioErrorType.response) {
      print('Error en la respuesta: ${e.response?.statusCode}');
    } else {
      print('Error de red: $e');
    }
  } catch (e) {
    print('Error desconocido: $e');
  }
}

  1. Ejemplo Práctico

Vamos a crear una aplicación simple que obtenga datos de una API y maneje los errores de red adecuadamente.

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('Manejo de Errores de Red')),
        body: DataFetcher(),
      ),
    );
  }
}

class DataFetcher extends StatefulWidget {
  @override
  _DataFetcherState createState() => _DataFetcherState();
}

class _DataFetcherState extends State<DataFetcher> {
  String _data = 'Presiona el botón para obtener datos';

  Future<void> fetchData() async {
    try {
      final response = await http.get(Uri.parse('https://api.example.com/data'));
      if (response.statusCode == 200) {
        final data = jsonDecode(response.body);
        setState(() {
          _data = 'Datos recibidos: $data';
        });
      } else {
        setState(() {
          _data = 'Error en la respuesta: ${response.statusCode}';
        });
      }
    } catch (e) {
      setState(() {
        _data = 'Error de red: $e';
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    return Center(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          Text(_data),
          SizedBox(height: 20),
          ElevatedButton(
            onPressed: fetchData,
            child: Text('Obtener Datos'),
          ),
        ],
      ),
    );
  }
}

  1. Ejercicio Práctico

Ejercicio

Crea una aplicación Flutter que obtenga datos de una API pública (por ejemplo, https://jsonplaceholder.typicode.com/posts) y maneje los errores de red. Muestra los datos en una lista y maneja los siguientes errores:

  1. Error de Conexión: Muestra un mensaje de error si no se puede conectar al servidor.
  2. Error de Respuesta: Muestra un mensaje de error si el servidor responde con un código de estado HTTP que indica un error.
  3. Error de Parseo: Muestra un mensaje de error si la respuesta no se puede convertir al formato esperado.

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('Manejo de Errores de Red')),
        body: PostList(),
      ),
    );
  }
}

class PostList extends StatefulWidget {
  @override
  _PostListState createState() => _PostListState();
}

class _PostListState extends State<PostList> {
  List<dynamic> _posts = [];
  String _error = '';

  Future<void> fetchPosts() async {
    try {
      final response = await http.get(Uri.parse('https://jsonplaceholder.typicode.com/posts'));
      if (response.statusCode == 200) {
        final data = jsonDecode(response.body);
        setState(() {
          _posts = data;
          _error = '';
        });
      } else {
        setState(() {
          _error = 'Error en la respuesta: ${response.statusCode}';
        });
      }
    } catch (e) {
      setState(() {
        _error = 'Error de red: $e';
      });
    }
  }

  @override
  void initState() {
    super.initState();
    fetchPosts();
  }

  @override
  Widget build(BuildContext context) {
    return _error.isNotEmpty
        ? Center(child: Text(_error))
        : ListView.builder(
            itemCount: _posts.length,
            itemBuilder: (context, index) {
              return ListTile(
                title: Text(_posts[index]['title']),
                subtitle: Text(_posts[index]['body']),
              );
            },
          );
  }
}

Conclusión

En esta lección, aprendiste cómo manejar errores de red en Flutter utilizando try-catch, async-await y paquetes de terceros como dio. También implementaste un ejemplo práctico y un ejercicio para reforzar los conceptos aprendidos. Ahora estás mejor preparado para manejar errores de red en tus aplicaciones Flutter, mejorando así la robustez y la experiencia del usuario.

Curso de Desarrollo con Flutter

Módulo 1: Introducción a Flutter

Módulo 2: Conceptos Básicos de Programación en Dart

Módulo 3: Widgets en Flutter

Módulo 4: Gestión de Estado

Módulo 5: Navegación y Enrutamiento

Módulo 6: Redes y APIs

Módulo 7: Persistencia y Almacenamiento

Módulo 8: Conceptos Avanzados de Flutter

Módulo 9: Pruebas y Depuración

Módulo 10: Despliegue y Mantenimiento

Módulo 11: Flutter para Web y Escritorio

© Copyright 2024. Todos los derechos reservados