1. Dealing with asynchronously
Note that the HTTP APIs use Dart Futures in the return values. We recommend using the API calls with the async/await syntax.
The networking calls generally follow a stepped approach:
- Create the client.
- Construct the Uri.
- Invoke the operation, and await the request object. Optionally, configure the headers and body of the request.
- Close the request, and await the response.
- Decode the response.
Several of these steps use Future based APIs. Sample APIs calls for each step above are:
import 'dart:convert';
import 'package:http/http.dart' as http;
import 'user_model.dart';
class ApiService {
static const String baseUrl = 'https://jsonplaceholder.typicode.com';
/// GET - List of Users
static Future<List<UserModel>> getUsers() async {
final response = await http.get(Uri.parse('$baseUrl/users'));
if (response.statusCode == 200) {
List data = jsonDecode(response.body);
// List<Map> -> List<Model>
return data.map((e) => UserModel.fromJson(e)).toList();
} else {
throw Exception('Failed to load users');
}
}
/// GET - Single User
static Future<UserModel> getUser(int id) async {
final response = await http.get(Uri.parse('$baseUrl/users/$id'));
if (response.statusCode == 200) {
Map<String, dynamic> data = jsonDecode(response.body);
return UserModel.fromJson(data);
} else {
throw Exception('Failed to load user');
}
}
/// POST - Create User
static Future<UserModel> createUser(UserModel user) async {
final response = await http.post(
Uri.parse('$baseUrl/users'),
headers: {'Content-Type': 'application/json'},
body: jsonEncode(user.toJson()),
);
if (response.statusCode == 201) {
Map<String, dynamic> data = jsonDecode(response.body);
return UserModel.fromJson(data);
} else {
throw Exception('Failed to create user');
}
}
}
- Model Class (User Model)
Example JSON:
class UserModel {
final int id;
final String name;
final String email;
UserModel({
required this.id,
required this.name,
required this.email,
});
// From JSON (Map -> Model)
factory UserModel.fromJson(Map<String, dynamic> json) {
return UserModel(
id: json['id'] ?? 0,
name: json['name'] ?? '',
email: json['email'] ?? '',
);
}
// To JSON (Model -> Map)
Map<String, dynamic> toJson() {
return {
'id': id,
'name': name,
'email': email,
};
}
}
- Simple UI Example main.dart
import 'package:flutter/material.dart';
import 'api_service.dart';
import 'user_model.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return const MaterialApp(
home: UserScreen(),
);
}
}
class UserScreen extends StatefulWidget {
const UserScreen({super.key});
@override
State<UserScreen> createState() => _UserScreenState();
}
class _UserScreenState extends State<UserScreen> {
List<UserModel> users = [];
bool isLoading = false;
@override
void initState() {
super.initState();
fetchUsers();
}
Future<void> fetchUsers() async {
setState(() => isLoading = true);
try {
users = await ApiService.getUsers();
} catch (e) {
print(e);
}
setState(() => isLoading = false);
}
Future<void> addUser() async {
UserModel newUser = UserModel(
id: 0,
name: "Devik",
email: "devik@test.com",
);
try {
UserModel createdUser = await ApiService.createUser(newUser);
setState(() {
users.add(createdUser);
});
} catch (e) {
print(e);
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text("API Demo")),
body: isLoading
? const Center(child: CircularProgressIndicator())
: ListView.builder(
itemCount: users.length,
itemBuilder: (context, index) {
final user = users[index];
return ListTile(
title: Text(user.name),
subtitle: Text(user.email),
);
},
),
floatingActionButton: FloatingActionButton(
onPressed: addUser,
child: const Icon(Icons.add),
),
);
}
}
Top comments (0)