Api Structure with Http
Source: Dev.to
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.
- Create the client.
- Construct the
Uri. - Invoke the operation, and
awaitthe request object. Optionally, configure the headers and body of the request. - Close the request, and
awaitthe response. - Decode the response.
Several of these steps use Future‑based APIs.
Sample API Calls
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> getUsers() async {
final response = await http.get(Uri.parse('$baseUrl/users'));
if (response.statusCode == 200) {
List data = jsonDecode(response.body);
// List -> List
return data.map((e) => UserModel.fromJson(e)).toList();
} else {
throw Exception('Failed to load users');
}
}
/// GET – Single User
static Future getUser(int id) async {
final response = await http.get(Uri.parse('$baseUrl/users/$id'));
if (response.statusCode == 200) {
Map data = jsonDecode(response.body);
return UserModel.fromJson(data);
} else {
throw Exception('Failed to load user');
}
}
/// POST – Create User
static Future 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 data = jsonDecode(response.body);
return UserModel.fromJson(data);
} else {
throw Exception('Failed to create user');
}
}
}Model Class (User Model)
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 json) {
return UserModel(
id: json['id'] ?? 0,
name: json['name'] ?? '',
email: json['email'] ?? '',
);
}
// To JSON (Model → Map)
Map 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 createState() => _UserScreenState();
}
class _UserScreenState extends State {
List users = [];
bool isLoading = false;
@override
void initState() {
super.initState();
fetchUsers();
}
Future fetchUsers() async {
setState(() => isLoading = true);
try {
users = await ApiService.getUsers();
} catch (e) {
print(e);
}
setState(() => isLoading = false);
}
Future 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),
),
);
}
}