This guide walks you through making REST API calls in Flutter, from the basic setup to handling responses and errors. You’ll learn how to use the http package, parse JSON, and structure your code for maintainability, with working examples you can adapt.
What You Need Before Starting
To follow along, you should have Flutter installed and a basic understanding of Dart. You’ll also need a REST API endpoint to test with—if you don’t have one, you can use a public test API like jsonplaceholder.typicode.com or reqres.in. These are free, fake APIs designed for practice, returning typical JSON data.
Your Flutter project should be created with flutter create. You’ll add the http package to your pubspec.yaml file (the current version is 1.x). Run flutter pub get to install it.
Adding the HTTP Package
The http package is the simplest way to make network calls in Flutter. It’s maintained by the Dart team and supports all common HTTP methods (GET, POST, PUT, DELETE).
- Open
pubspec.yaml. - Under
dependencies, addhttp: ^1.2.0(use the latest version). - Run
flutter pub getin your terminal.
Alternatively, you can use the dio package, which offers more features like interceptors and file uploads, but for most beginners, http is sufficient and easier to learn.
Making a Simple GET Request
Here’s a minimal example that fetches a list of posts from a public API and prints the response body.
import 'package:http/http.dart' as http;
Future<void> fetchPosts() async {
final response = await http.get(
Uri.parse('https://jsonplaceholder.typicode.com/posts'),
);
if (response.statusCode == 200) {
print(response.body);
} else {
throw Exception('Failed to load posts');
}
}
Key points:
- Use
Uri.parse()to convert a string URL into aUriobject. http.get()returns aResponseobject.- Check
statusCodeto see if the request succeeded (200-299). - The response body is a JSON string; you’ll need to decode it.
Parsing JSON Responses
JSON is the standard format for REST APIs. Flutter provides the dart:convert library to decode JSON strings into Dart objects.
For a single object, you can use jsonDecode:
import 'dart:convert';
final data = jsonDecode(response.body) as Map<String, dynamic>;
print(data['title']);
For a list, you’d cast to List and iterate:
final list = jsonDecode(response.body) as List;
for (var item in list) {
print(item['title']);
}
For better code organization, create model classes. For example, a Post class with fromJson factory:
class Post {
final int userId;
final int id;
final String title;
final String body;
Post({required this.userId, required this.id, required this.title, required this.body});
factory Post.fromJson(Map<String, dynamic> json) {
return Post(
userId: json['userId'],
id: json['id'],
title: json['title'],
body: json['body'],
);
}
}
Then you can map the JSON list to Post objects:
List<Post> posts = list.map((json) => Post.fromJson(json)).toList();
Handling Errors and Timeouts
Network calls can fail for many reasons: no internet, server errors, or timeouts. Always handle exceptions.
Wrap your call in a try-catch block:
try {
final response = await http.get(uri).timeout(Duration(seconds: 10));
if (response.statusCode == 200) {
// success
} else {
// server error
}
} on TimeoutException {
// handle timeout
} catch (e) {
// handle other errors
}
The .timeout() method prevents your app from hanging indefinitely. For user-friendly error messages, you can throw custom exceptions or return a result object with an error state.
Using the Data in Your UI
To display fetched data, use a FutureBuilder or a StatefulWidget with setState.
Example with FutureBuilder:
Future<List<Post>> _getPosts() async {
// your fetch function
}
FutureBuilder<List<Post>>(
future: _getPosts(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return CircularProgressIndicator();
} else if (snapshot.hasError) {
return Text('Error: ${snapshot.error}');
} else {
return ListView.builder(
itemCount: snapshot.data!.length,
itemBuilder: (context, index) {
return ListTile(title: Text(snapshot.data![index].title));
},
);
}
},
)
Always show a loading indicator while waiting, and handle errors gracefully—don’t just crash.
POST, PUT, and DELETE Requests
Besides GET, you’ll often need to send data. For POST, you include a body with the data:
final response = await http.post(
Uri.parse('https://jsonplaceholder.typicode.com/posts'),
headers: {'Content-Type': 'application/json'},
body: jsonEncode({
'title': 'New Post',
'body': 'Content',
'userId': 1,
}),
);
PUT and DELETE are similar—use http.put() and http.delete(). The server’s response will tell you if the operation succeeded (status code 200, 201, 204, etc.).
Common Mistakes and How to Avoid Them
- Forgetting to decode JSON: The response body is a string; you must call
jsonDecodebefore accessing fields. - Not checking status codes: Always verify that the response is successful before parsing.
- Blocking the UI thread: Always use
async/awaitor futures; never make synchronous network calls. - Ignoring timeouts: Use
.timeout()to avoid hanging. - Hardcoding URLs: Use constants or configuration files for API endpoints.
Frequently Asked Questions
How do I add headers to a request?
Pass a headers map to the request method. For example, to send an API key: http.get(uri, headers: {'Authorization': 'Bearer your_token'}).
What’s the difference between http and dio?
http is a lightweight, official package; dio is a third-party package with more features like interceptors, cancellation, and file upload. For simple apps, http is enough.
How do I handle nested JSON objects?
Create model classes for each level. For example, if a post has an author object, create an Author class and parse it inside Post.fromJson.
Why am I getting a CORS error?
CORS is a browser security feature; it doesn’t apply to mobile apps or desktop. If you’re testing in Flutter web, you may need to add CORS headers to your API or use a proxy.
How can I test my API calls without a real server?
Use mock interceptors like http_mock_adapter or simply test with a public fake API. You can also create a mock server locally using packages like mocktail.
Related
Method: the standard formula for this calculation, rounded as each result states. See how the calculators work or report an error.
More cards in this drawer
- Valheim Server Not Showing in Community List Fixes
- Soundbar vs 2.1 Speaker System: Which Is Better?
- DisplayPort vs HDMI: Which Cable Should You Use?
- Survive Lava for Brainrot Tier List170 points
- MySQL Dump Import: Fix Common Errors
- Mouse Moving on Its Own? Causes & Fixes