Actualizar datos a través de internet
Cómo utilizar el paquete http para actualizar datos en Internet.
Actualizar datos a través de internet es necesario para la mayoría de las aplicaciones.
¡El paquete http lo tiene cubierto!
Esta receta utiliza los siguientes pasos:
- Agrega el paquete
http. - Actualiza datos a través de internet utilizando el paquete
http. - Convierte la respuesta en un objeto Dart personalizado.
- Obtener los datos de internet.
- Actualiza el
títuloexistente a partir de la entrada del usuario. - Actualizar y mostrar la respuesta en pantalla.
1. Agregar el paquete http
#
Para agregar el paquete http como dependencia,
ejecuta flutter pub add:
flutter pub add http
Importa el paquete http.
import 'package:http/http.dart' as http;
Si estás haciendo el despliegue en Android, edita tu archivo AndroidManifest.xml para
agregar el permiso de Internet.
<!-- Required to fetch data from the internet. -->
<uses-permission android:name="android.permission.INTERNET" />
Del mismo modo, si estás haciendo el despliegue en macOS, edita tus
archivos macos/Runner/DebugProfile.entitlements y macos/Runner/Release.entitlements
para incluir el entitlement del cliente de red.
<!-- Required to fetch data from the internet. -->
<key>com.apple.security.network.client</key>
<true/>
2. Actualizar datos a través de internet utilizando el paquete http
#
Esta receta cubre cómo actualizar el título de un álbum en
JSONPlaceholder utilizando el método http.put().
Future<http.Response> updateAlbum(String title) {
return http.put(
Uri.parse('https://jsonplaceholder.typicode.com/albums/1'),
headers: <String, String>{
'Content-Type': 'application/json; charset=UTF-8',
},
body: jsonEncode(<String, String>{'title': title}),
);
}
El método http.put() devuelve un Future que contiene una Response.
Futurees una clase principal de Dart para trabajar con operaciones asíncronas. Un objetoFuturerepresenta un valor potencial o un error que estará disponible en algún momento en el futuro.- La clase
http.Responsecontiene los datos recibidos de una llamada http exitosa. - El método
updateAlbum()toma un argumento,title, que se envía al servidor para actualizar elAlbum.
3. Convertir http.Response en un objeto Dart personalizado
#
Aunque es fácil realizar una solicitud de red,
trabajar con un Future<http.Response>
crudo no es muy conveniente. Para facilitarte la vida,
convierte la http.Response en un objeto de Dart.
Crear una clase Album
#Primero, crea una clase Album que contenga los datos de la
solicitud de red. Incluye un constructor factory que
crea un Album a partir de JSON.
Convertir JSON utilizando pattern matching es solo una opción. Para obtener más información, consulta el artículo completo sobre JSON y serialización.
class Album {
final int id;
final String title;
const Album({required this.id, required this.title});
factory Album.fromJson(Map<String, dynamic> json) {
return switch (json) {
{'id': int id, 'title': String title} => Album(id: id, title: title),
_ => throw const FormatException('Failed to load album.'),
};
}
}
Convertir la http.Response en un Album
#
Ahora, utiliza los siguientes pasos para actualizar la función updateAlbum()
para que devuelva un Future<Album>:
- Convierte el cuerpo de la respuesta en un JSON
Mapcon el paquetedart:convert. - Si el servidor devuelve una respuesta
UPDATEDcon un código de estado de 200, entonces convierte el JSONMapen unAlbumutilizando el método factoryfromJson(). - Si el servidor no devuelve una respuesta
UPDATEDcon un código de estado de 200, entonces lanza una excepción. (Incluso en el caso de una respuesta del servidor "404 Not Found", lanza una excepción. No devuelvasnull. Esto es importante al examinar los datos ensnapshot, como se muestra a continuación).
Future<Album> updateAlbum(String title) async {
final response = await http.put(
Uri.parse('https://jsonplaceholder.typicode.com/albums/1'),
headers: <String, String>{
'Content-Type': 'application/json; charset=UTF-8',
},
body: jsonEncode(<String, String>{'title': title}),
);
if (response.statusCode == 200) {
// If the server did return a 200 OK response,
// then parse the JSON.
return Album.fromJson(jsonDecode(response.body) as Map<String, dynamic>);
} else {
// If the server did not return a 200 OK response,
// then throw an exception.
throw Exception('Failed to update album.');
}
}
¡Genial! Ahora tienes una función que actualiza el título de un álbum.
Obtener los datos de internet
#Obtén los datos de internet antes de poder actualizarlos. Para ver un ejemplo completo, consulta la receta Obtener datos.
Future<Album> fetchAlbum() async {
final response = await http.get(
Uri.parse('https://jsonplaceholder.typicode.com/albums/1'),
);
if (response.statusCode == 200) {
// If the server did return a 200 OK response,
// then parse the JSON.
return Album.fromJson(jsonDecode(response.body) as Map<String, dynamic>);
} else {
// If the server did not return a 200 OK response,
// then throw an exception.
throw Exception('Failed to load album');
}
}
Idealmente, utilizarás este método para establecer
_futureAlbum durante initState para obtener
los datos de internet.
4. Actualizar el título existente a partir de la entrada del usuario
#Crea un TextField para ingresar un título y un ElevatedButton
para actualizar los datos en el servidor.
También define un TextEditingController para
leer la entrada del usuario desde un TextField.
Cuando se presiona el ElevatedButton,
el _futureAlbum se establece con el valor devuelto por el
método updateAlbum().
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Padding(
padding: const EdgeInsets.all(8),
child: TextField(
controller: _controller,
decoration: const InputDecoration(hintText: 'Enter Title'),
),
),
ElevatedButton(
onPressed: () {
setState(() {
_futureAlbum = updateAlbum(_controller.text);
});
},
child: const Text('Update Data'),
),
],
);
Al presionar el botón Actualizar datos, una solicitud de red
envía los datos del TextField al servidor como una solicitud PUT.
La variable _futureAlbum se utiliza en el siguiente paso.
5. Mostrar la respuesta en pantalla
#Para mostrar los datos en pantalla, utiliza el
widget FutureBuilder.
El widget FutureBuilder viene con Flutter y
facilita el trabajo con fuentes de datos asíncronas.
Debes proporcionar dos parámetros:
- El
Futurecon el que quieres trabajar. En este caso, el future devuelto por la funciónupdateAlbum(). - Una función
builderque le indica a Flutter qué renderizar, según el estado delFuture: cargando, éxito o error.
Ten en cuenta que snapshot.hasData solo devuelve true cuando
el snapshot contiene un valor de datos no nulo.
Es por eso que la función updateAlbum debe lanzar una excepción
incluso en el caso de una respuesta del servidor "404 Not Found".
Si updateAlbum devuelve null, entonces el
CircularProgressIndicator se mostrará indefinidamente.
FutureBuilder<Album>(
future: _futureAlbum,
builder: (context, snapshot) {
if (snapshot.hasData) {
return Text(snapshot.data!.title);
} else if (snapshot.hasError) {
return Text('${snapshot.error}');
}
return const CircularProgressIndicator();
},
);
Ejemplo completo
#import 'dart:async';
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
Future<Album> fetchAlbum() async {
final response = await http.get(
Uri.parse('https://jsonplaceholder.typicode.com/albums/1'),
);
if (response.statusCode == 200) {
// If the server did return a 200 OK response,
// then parse the JSON.
return Album.fromJson(jsonDecode(response.body) as Map<String, dynamic>);
} else {
// If the server did not return a 200 OK response,
// then throw an exception.
throw Exception('Failed to load album');
}
}
Future<Album> updateAlbum(String title) async {
final response = await http.put(
Uri.parse('https://jsonplaceholder.typicode.com/albums/1'),
headers: <String, String>{
'Content-Type': 'application/json; charset=UTF-8',
},
body: jsonEncode(<String, String>{'title': title}),
);
if (response.statusCode == 200) {
// If the server did return a 200 OK response,
// then parse the JSON.
return Album.fromJson(jsonDecode(response.body) as Map<String, dynamic>);
} else {
// If the server did not return a 200 OK response,
// then throw an exception.
throw Exception('Failed to update album.');
}
}
class Album {
final int id;
final String title;
const Album({required this.id, required this.title});
factory Album.fromJson(Map<String, dynamic> json) {
return switch (json) {
{'id': int id, 'title': String title} => Album(id: id, title: title),
_ => throw const FormatException('Failed to load album.'),
};
}
}
void main() {
runApp(const MyApp());
}
class MyApp extends StatefulWidget {
const MyApp({super.key});
@override
State<MyApp> createState() {
return _MyAppState();
}
}
class _MyAppState extends State<MyApp> {
final TextEditingController _controller = TextEditingController();
late Future<Album> _futureAlbum;
@override
void initState() {
super.initState();
_futureAlbum = fetchAlbum();
}
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Update Data Example',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
),
home: Scaffold(
appBar: AppBar(title: const Text('Update Data Example')),
body: Container(
alignment: Alignment.center,
padding: const EdgeInsets.all(8),
child: FutureBuilder<Album>(
future: _futureAlbum,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
if (snapshot.hasData) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(snapshot.data!.title),
TextField(
controller: _controller,
decoration: const InputDecoration(
hintText: 'Enter Title',
),
),
ElevatedButton(
onPressed: () {
setState(() {
_futureAlbum = updateAlbum(_controller.text);
});
},
child: const Text('Update Data'),
),
],
);
} else if (snapshot.hasError) {
return Text('${snapshot.error}');
}
}
return const CircularProgressIndicator();
},
),
),
),
);
}
}
A menos que se indique lo contrario, la documentación de este sitio refleja Flutter 3.44.0. Página actualizada por última vez el 2026-05-05. Ver código fuente oreportar un problema.