1. Understanding How Flutter Interacts With the Backend #
Before using any backend technologies or building APIs, it is important to understand how Flutter communicates with servers. Flutter itself does not contain backend capabilities—it relies on external services, REST APIs, databases, and cloud functions to retrieve or send data. This interaction happens over the internet using standard communication protocols such as HTTP.
Why This Matters #
Most real-world Flutter applications rely on backend data for features such as:
- User authentication
- Fetching product lists or posts
- Submitting forms and images
- Storing user preferences
- Real-time updates
To handle all of this, understanding how Flutter talks to a server is the foundation of backend development.
Core Concepts #
1. What is a REST API? #
A REST API (Representational State Transfer) is a standard way for apps to communicate with servers.
- It works over HTTP.
- It exposes endpoints (URLs) that your Flutter app can request or send data to.
- It uses JSON format for communication.
Example REST API endpoint:
https://api.myapp.com/users
A REST API allows you to perform CRUD operations:
| Operation | HTTP Method | Purpose |
|---|---|---|
| Create | POST | Add new data |
| Read | GET | Retrieve data |
| Update | PUT/PATCH | Modify existing data |
| Delete | DELETE | Remove data |
2. HTTP Requests (GET, POST, PUT, DELETE) #
HTTP is the protocol for communication between client and server.
GET Request Example #
Fetching user data:
final response = await http.get(Uri.parse('https://api.example.com/users'));
POST Request Example #
Sending new user data:
final response = await http.post(
Uri.parse('https://api.example.com/users'),
body: {'name': 'Ali', 'age': '22'},
);
PUT Request Example #
Updating user data:
await http.put(
Uri.parse('https://api.example.com/users/1'),
body: {'name': 'Updated Name'},
);
DELETE Request Example #
Deleting user data:
await http.delete(Uri.parse('https://api.example.com/users/1'));
3. JSON Structure #
Most modern APIs return data in JSON format.
Example JSON #
{
"id": 1,
"name": "Ali",
"email": "ali@example.com"
}
Flutter reads and converts this JSON into a Dart object.
4. Serialization & Deserialization #
Deserialization #
Converting JSON → Dart Model
class User {
final int id;
final String name;
User({required this.id, required this.name});
factory User.fromJson(Map<String, dynamic> json) {
return User(
id: json['id'],
name: json['name'],
);
}
}
Serialization #
Converting Dart Model → JSON
Map<String, dynamic> toJson() {
return {
'id': id,
'name': name,
};
}
This is essential for sending and receiving data cleanly.
5. Client–Server Model #
Flutter (Client)
⬇️ Sends request
Server (Backend API)
⬆️ Returns response
Workflow:
- User taps a button
- Flutter sends HTTP request
- Backend processes the request
- Backend sends JSON response
- Flutter displays the result in UI
This architecture separates frontend and backend responsibilities.
6. API Endpoints and Status Codes #
API Endpoint #
A specific URL in your backend that performs a certain action.
Example:
GET https://api.example.com/products
Status Codes #
These indicate success or failure:
| Code | Meaning |
|---|---|
| 200 | OK – request successful |
| 201 | Created – new resource added |
| 400 | Bad request |
| 401 | Unauthorized |
| 404 | Not found |
| 500 | Server error |
Flutter should always check status codes before parsing data.
Example:
if (response.statusCode == 200) {
// parse data
} else {
// handle error
}
Flutter Packages to Learn #
1. http #
Lightweight package for basic HTTP operations.
Use for:
- Simple APIs
- Quick network calls
- Beginners learning REST APIs
Install:
dependencies: http: ^1.2.0
2. dio #
A powerful HTTP client with advanced features.
Supports:
- Interceptors
- Global configuration
- Auto retries
- File uploads
- Cancellation tokens
Install:
dependencies: dio: ^5.0.0
3. json_serializable #
Automatically generates JSON parsing code.
Why use it:
- Reduces boilerplate
- More reliable
- Works well with large models
Install:
dependencies: json_annotation: ^4.8.0 dev_dependencies: build_runner: ^2.4.0 json_serializable: ^6.6.0
4. retrofit #
A declarative API client generator (built on Dio).
Use when:
- Building cleaner, scalable backend logic
- You want easy network layer management
Example:
@RestApi(baseUrl: "https://api.example.com")
abstract class ApiService {
factory ApiService(Dio dio) = _ApiService;
@GET("/users")
Future<List<User>> getUsers();
}
Best Practices #
✔ Always use HTTPS
✔ Handle errors (timeouts, no internet, 400+ codes)
✔ Use models instead of dynamic JSON
✔ Organize API code in a separate service layer
✔ Use dio + retrofit for large apps
✔ Use json_serializable for clean JSON parsing
✔ Avoid writing API logic inside widgets
✔ Cache data when needed (Hive, SharedPreferences)