En este tema, aprenderás cómo integrar GraphQL en tu aplicación Flutter para realizar consultas y mutaciones de datos. GraphQL es un lenguaje de consulta para APIs que permite a los clientes solicitar exactamente los datos que necesitan, lo que puede mejorar la eficiencia y la flexibilidad de las aplicaciones.
Objetivos de Aprendizaje
- Comprender los conceptos básicos de GraphQL.
- Configurar un cliente GraphQL en Flutter.
- Realizar consultas y mutaciones utilizando GraphQL.
- Manejar errores y respuestas de GraphQL.
Conceptos Básicos de GraphQL
¿Qué es GraphQL?
GraphQL es un lenguaje de consulta para APIs y un entorno de ejecución para realizar esas consultas con tus datos existentes. Fue desarrollado por Facebook y ofrece una alternativa a las APIs REST tradicionales.
Ventajas de GraphQL
- Solicitudes específicas: Los clientes pueden solicitar exactamente los datos que necesitan.
- Menos solicitudes: Permite obtener múltiples recursos en una sola solicitud.
- Evolución de la API: Facilita la evolución de la API sin afectar a los clientes existentes.
Componentes de GraphQL
- Schema: Define los tipos de datos y las relaciones entre ellos.
- Query: Solicita datos.
- Mutation: Modifica datos.
- Resolver: Funciones que resuelven una consulta o mutación.
Configuración del Cliente GraphQL en Flutter
Paso 1: Añadir Dependencias
Primero, necesitas añadir las dependencias necesarias en tu archivo pubspec.yaml.
Paso 2: Configurar el Cliente GraphQL
Configura el cliente GraphQL en tu aplicación Flutter. Esto generalmente se hace en el archivo main.dart.
import 'package:flutter/material.dart';
import 'package:graphql_flutter/graphql_flutter.dart';
void main() async {
await initHiveForFlutter();
final HttpLink httpLink = HttpLink(
'https://your-graphql-endpoint.com/graphql',
);
final GraphQLClient client = GraphQLClient(
cache: GraphQLCache(store: HiveStore()),
link: httpLink,
);
runApp(MyApp(client: client));
}
class MyApp extends StatelessWidget {
final GraphQLClient client;
MyApp({required this.client});
@override
Widget build(BuildContext context) {
return GraphQLProvider(
client: ValueNotifier(client),
child: MaterialApp(
home: HomeScreen(),
),
);
}
}Paso 3: Realizar una Consulta GraphQL
Para realizar una consulta, puedes usar el widget Query proporcionado por graphql_flutter.
import 'package:flutter/material.dart';
import 'package:graphql_flutter/graphql_flutter.dart';
class HomeScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
String readRepositories = """
query ReadRepositories {
viewer {
repositories(last: 50) {
nodes {
name
}
}
}
}
""";
return Scaffold(
appBar: AppBar(
title: Text('GraphQL Integration'),
),
body: Query(
options: QueryOptions(
document: gql(readRepositories),
),
builder: (QueryResult result, { VoidCallback? refetch, FetchMore? fetchMore }) {
if (result.hasException) {
return Text(result.exception.toString());
}
if (result.isLoading) {
return Center(child: CircularProgressIndicator());
}
List repositories = result.data!['viewer']['repositories']['nodes'];
return ListView.builder(
itemCount: repositories.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(repositories[index]['name']),
);
},
);
},
),
);
}
}Paso 4: Realizar una Mutación GraphQL
Para realizar una mutación, puedes usar el widget Mutation.
import 'package:flutter/material.dart';
import 'package:graphql_flutter/graphql_flutter.dart';
class AddRepositoryScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
String addRepository = """
mutation AddRepository(\$name: String!) {
createRepository(input: {name: \$name}) {
repository {
id
name
}
}
}
""";
return Scaffold(
appBar: AppBar(
title: Text('Add Repository'),
),
body: Mutation(
options: MutationOptions(
document: gql(addRepository),
),
builder: (RunMutation runMutation, QueryResult? result) {
return Column(
children: [
TextField(
decoration: InputDecoration(labelText: 'Repository Name'),
onSubmitted: (name) {
runMutation({'name': name});
},
),
if (result != null && result.hasException)
Text(result.exception.toString()),
if (result != null && result.isLoading)
CircularProgressIndicator(),
if (result != null && result.data != null)
Text('Repository Added: ${result.data!['createRepository']['repository']['name']}'),
],
);
},
),
);
}
}Manejo de Errores y Respuestas
Es importante manejar adecuadamente los errores y las respuestas de las consultas y mutaciones GraphQL.
Errores Comunes
- Errores de red: Problemas de conectividad.
- Errores de sintaxis: Errores en la consulta o mutación.
- Errores de autorización: Falta de permisos para acceder a ciertos datos.
Manejo de Errores
Puedes manejar los errores verificando la propiedad hasException del QueryResult.
Ejercicio Práctico
Ejercicio 1: Realizar una Consulta
- Configura un cliente GraphQL en tu aplicación Flutter.
- Realiza una consulta para obtener una lista de usuarios desde un endpoint GraphQL.
- Muestra los nombres de los usuarios en una lista.
Ejercicio 2: Realizar una Mutación
- Configura una mutación para añadir un nuevo usuario.
- Crea un formulario con un campo de texto para ingresar el nombre del usuario.
- Ejecuta la mutación al enviar el formulario y muestra un mensaje de éxito o error.
Soluciones
Solución Ejercicio 1
import 'package:flutter/material.dart';
import 'package:graphql_flutter/graphql_flutter.dart';
void main() async {
await initHiveForFlutter();
final HttpLink httpLink = HttpLink(
'https://your-graphql-endpoint.com/graphql',
);
final GraphQLClient client = GraphQLClient(
cache: GraphQLCache(store: HiveStore()),
link: httpLink,
);
runApp(MyApp(client: client));
}
class MyApp extends StatelessWidget {
final GraphQLClient client;
MyApp({required this.client});
@override
Widget build(BuildContext context) {
return GraphQLProvider(
client: ValueNotifier(client),
child: MaterialApp(
home: UserListScreen(),
),
);
}
}
class UserListScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
String readUsers = """
query ReadUsers {
users {
id
name
}
}
""";
return Scaffold(
appBar: AppBar(
title: Text('User List'),
),
body: Query(
options: QueryOptions(
document: gql(readUsers),
),
builder: (QueryResult result, { VoidCallback? refetch, FetchMore? fetchMore }) {
if (result.hasException) {
return Text(result.exception.toString());
}
if (result.isLoading) {
return Center(child: CircularProgressIndicator());
}
List users = result.data!['users'];
return ListView.builder(
itemCount: users.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(users[index]['name']),
);
},
);
},
),
);
}
}Solución Ejercicio 2
import 'package:flutter/material.dart';
import 'package:graphql_flutter/graphql_flutter.dart';
class AddUserScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
String addUser = """
mutation AddUser(\$name: String!) {
createUser(input: {name: \$name}) {
user {
id
name
}
}
}
""";
return Scaffold(
appBar: AppBar(
title: Text('Add User'),
),
body: Mutation(
options: MutationOptions(
document: gql(addUser),
),
builder: (RunMutation runMutation, QueryResult? result) {
return Column(
children: [
TextField(
decoration: InputDecoration(labelText: 'User Name'),
onSubmitted: (name) {
runMutation({'name': name});
},
),
if (result != null && result.hasException)
Text(result.exception.toString()),
if (result != null && result.isLoading)
CircularProgressIndicator(),
if (result != null && result.data != null)
Text('User Added: ${result.data!['createUser']['user']['name']}'),
],
);
},
),
);
}
}Conclusión
En esta sección, has aprendido cómo integrar GraphQL en tu aplicación Flutter. Has configurado un cliente GraphQL, realizado consultas y mutaciones, y manejado errores y respuestas. Con estos conocimientos, puedes aprovechar las ventajas de GraphQL para construir aplicaciones más eficientes y flexibles.
En el próximo módulo, exploraremos cómo manejar la persistencia y el almacenamiento en Flutter, incluyendo el uso de bases de datos locales y almacenamiento de archivos.
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
