
How To Implement API In Flutter
APIs are a fundamental part of many modern applications, and Flutter makes it easy to integrate them into your apps. In this article, we will walk you through the steps to implement an API in Flutter. In a growing world of mobile app development, it is necessary to craft efficient and responsive applications. Flutter, a popular open-source UI framework, has gained immense recognition for its ability to help developers build natively compiled applications for mobile, web, and desktop from a single codebase. To improve the functionality of a Flutter app, it is crucial to incorporate APIs within the application. Let's explore the procedure for integrating an API in Flutter.
What is API?
An API, or application programming interface, is a way for different software components to communicate with each other. It is used to exchange data and functionality between different applications and build complex and powerful applications.
APIs are a powerful way to connect your Flutter app to the backend. It allows you to fetch data, send requests, and update information from your app.
Why use API in Flutter?
There are many benefits to using an API in Flutter. APIs allow you to:
- Access data and functionality from other applications
- Build complex and powerful applications without having to develop all of the functionality yourself
- Make your apps more scalable and flexible
Also Read: Flutter App Permissions: A Complete Guide To Handle Permissions
Different Types of API Requests
There are four main types of API requests in Flutter:
1. GET Requests
GET requests can be used to retrieve data from a server. You can use a GET request to fetch a list of users from a database or to retrieve the details of a specific user. For example, the following GET request would retrieve a list of all users from the server:
GET /users
In addition, GET requests can be repeated without changing the state of the server. This makes them ideal for use in caching.
2. POST Requests
POST requests are used to create new data on the server. The data that is created is specified in the request body. For example, the following POST request would create a new user on the server:
POST /users { "name": “Test”, "email": "[email protected]" }
It typically takes body parameters, which are the data that is being created. For example, you could use body parameters to specify the user's name, email address, and password when creating a new user account.
3. PUT Requests
PUT requests are used to update existing data on the server. The data that is updated is specified in the request body. For example, the following PUT request would update the name of the user with the ID of 1:
PUT /users/1 { "name": "Test" }
4. DELETE Requests
DELETE requests are used to delete a resource from the server. The resource that is deleted is specified in the request URL. For example, the following DELETE request would delete the user with the ID of 1:
DELETE /users/1
5. PATCH Requests
The HTTP PATCH request method is used to apply partial modifications to a resource. Similarly to POST requests, PATCH requests can potentially impact other resources. To determine whether a server supports PATCH requests, the server can include it in the list of supported methods in the Allow or Access-Control-Allow-Methods response headers (for CORS).
PATCH /test.txt HTTP/1.1 Host: www.codetrade.io Content-Type: application/example If-Match: "e0023aa4e" Content-Length: 100 [description of changes]
An additional (implicit) indication that PATCH requests are supported is the presence of the Accept-Patch header, which informs clients about the patch document formats that the server can process.
Let’s check the initial steps to implement API in Flutter.
Explore More: Empower Your App Development with Top-Rated Flutter Developers
Implementation of API in Flutter
There are many different ways to implement an API in Flutter, but the general process is the same:
1. Choose an HTTP Package
There are a number of different HTTP packages available for Flutter, such as http, dio, and chopper. Each package has its own strengths and weaknesses, so choose one that best suits your needs. To add the http package, open your pubspec.yaml file and add the following dependency:
dependencies: http: ^0.13.3
Then, run the following command to install the package:
flutter pub get
2. Create a Model Class
Next, we need to create a model class to represent the data returned by the API. This will make it easier to parse the JSON response and use the data in your app.
3. Make The API Call
This function will take the URL of the API endpoint and any required parameters as input and return a Future of the response.
4. Use the FutureBuilder Widget
Use the FutureBuilder widget to display the data returned by the API. The FutureBuilder widget will handle all of the state management and error handling for you.
Let’s take a complete example of how to implement an API in the Flutter Application.
Best practices for API integration in Flutter
class ApiHandler {
static final ApiHandler _instance = ApiHandler._internal();
ApiHandler._internal();
factory ApiHandler() {
return _instance;
}
Future apiCalling(var url, Map bodyMap, ApiMethods methodType,
{Map<String, dynamic>? queryParameters}) async {
Map result;
Map<String, String> headers = {
'Content-Type': 'application/json',
'Accept': 'application/json',
};
switch (methodType) {
case ApiMethods.post:
log("token----------------$loginToken");
if (loginToken.isNotEmpty) {
headers['Authorization'] = 'Token $loginToken';
}
try {
log("login token$loginToken");
log(headers.toString());
Response response = await http.post(Uri.parse(url),
body: jsonEncode(bodyMap), headers: headers);
result = json.decode(response.body);
log(response.body);
log(result.toString());
responseHandling(ApiResponse(
data: result,
statusCode: response.statusCode,
));
log(response.statusCode.toString());
return result;
} catch (e) {
log(e.toString());
}
break;
case ApiMethods.get:
try {
log("token----------------$loginToken");
var uri = Uri.parse(url);
if (queryParameters != null) {
uri = Uri.parse(url).replace(queryParameters: queryParameters);
}
loginToken =
await SharedPreferenceController().getStringValue("loginToken");
log("token----------------$loginToken");
var response = await http.get(URI, headers: {
'Content-Type': 'application/json',
'Accept': 'application/json',
'Authorization': 'Token $loginToken',
});
result = json.decode(response.body);
responseHandling(ApiResponse(
data: result,
statusCode: response.statusCode,
));
return result;
} catch (e) {
log(e.toString());
}
break;
case ApiMethods.put:
log("token----------------$loginToken");
if (loginToken.isNotEmpty) {
headers['Authorization'] = 'Token $loginToken';
}
try {
log("login token$loginToken");
log(headers.toString());
Response response = await http.put(Uri.parse(url),
body: jsonEncode(bodyMap), headers: headers);
result = json.decode(response.body);
responseHandling(ApiResponse(
data: result,
statusCode: response.statusCode,
));
log('$result');
log(response.body);
log(response.statusCode.toString());
return result;
} catch (e) {
log(e.toString());
}
break;
}
}
void responseHandling(ApiResponse resp) async {
if (resp.statusCode == 200) {
log('------------request ssucceeded');
} else if (resp.statusCode == 400) {
log('400 Bad request status code ');
} else if (resp.statusCode == 404) {
log('404 Resource not found ');
} else if (resp.statusCode == 500) {
log('500 Internal server error');
} else if (resp.statusCode == 503) {
log('Service Unavailable');
} else if (resp.statusCode == 502) {
log('Bad Gateway');
} else if (resp.statusCode == 401) {
log('Token is expired or invalid');
loginToken = '';
await SharedPreferenceController().setStringValue("loginToken", '');
Get.offAllNamed(routeSignIn);
}
}
}
In the code, we used a singleton class called ApiHandler. It is used to make API calls and handle responses.
apiCalling() function
The apiCalling() function is responsible for making API calls and handling the responses. It requires the following parameters:
- url: The URL of the API endpoint.
- bodyMap: A map of the body parameters to be sent with the request.
- methodType: The HTTP method to use for the request, such as GET, POST, PUT, or DELETE.
- queryParameters: A map of the query parameters to be sent with the request.
The apiCalling() function asynchronously retrieves data from an API endpoint and returns a Future object containing the API response. The response is a Map structure encapsulating the data retrieved from the API.
responseHandling() Method
The responseHandling() function processes the response received from an API call. It accepts the following parameters:
resp: An ApiResponse object.
The responseHandling() function analyzes the status code of the API response and initiates the appropriate actions based on the code. For instance, if it encounters a status code of 401, indicating unauthorized access, it logs out the user and redirects them to the login page.
How To Call ApiHandler Class In Any Function For Call API
To call the ApiHandler class in any function for calling an API, you can follow the given code:
Future<void> apiLogin() async {
final bodyMap = {
"email": emailController.text,
"password": passController.text,
"registration_id":
await SharedPreferenceController().getStringValue("FCMtoken"),
"device_id": deviceId,
"device_type": deviceType
};
try {
final res = await apiHandler.apiCalling(loginUrl, bodyMap, ApiMethods.post);
if(res != null){
LoginResponse loginResponse = LoginResponse.fromJson(res);
if (loginResponse.error == null) {
if (mounted) {
await getData();
await setData(loginResponse.data.token);
log("result---------------${loginResponse.data.token}");
Get.back();
if (mounted) {
Get.offNamed(routeHome);
}
}
} else {
Get.back();
}
}else{
Get.back();
}
} catch (e) {
Get.back();
}
}
This code defines an asynchronous function called apiLogin() that is responsible for handling the login process using the apiHandler class and the provided API endpoint URL (loginUrl).
Note: Replace the loginUrl with your specific URL and utilize the provided code for your intended use.
How to Use FutureBuilder Widget to Display Data Retrieved From API
The FutureBuilder widget in Flutter is useful to build UI based on the latest snapshot of interaction with a Future. This makes it ideal for displaying data from an API.
To utilize the FutureBuilder widget with an API, you'll first need to create a function that returns a Future object. This function will typically involve making an HTTP request to the API and encapsulating the response data within the Future.
Once you've created this function, you can proceed to construct a FutureBuilder widget. The FutureBuilder widget requires two essential arguments:
future: The Future object that you want to build your UI based on.
builder: A builder function called to build the UI based on the current state of the Future.
The builder function receives a single argument, a Snapshot object, which encapsulates information about the current state of the Future. This information includes whether the Future has completed, the data it has returned, and any errors that may have occurred during the process.
FutureBuilder<NewsApiResponse>(
future: futureNews,
builder: (context, snapshot) {
if (snapshot.hasData) {
return ListView.builder(
itemCount: snapshot.data!.articles.length,
itemBuilder: (context, index) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: Card(
child: ListTile(
title: Text(
snapshot.data!.articles[index].title,
style: const TextStyle(fontWeight: FontWeight.bold),
),
subtitle:
Text(snapshot.data!.articles[index].description),
),
),
);
},
);
} else if (snapshot.hasError) {
return Center(child: Text('${snapshot.error}'));
}
return const Center(child: CircularProgressIndicator());
},
)
This code snippet represents a Flutter widget that utilizes the FutureBuilder widget to display data from a Future object named futureNews. The FutureBuilder widget dynamically adapts the UI based on the state of the Future object.
Code effectively utilizes the FutureBuilder widget to render a dynamic list of news articles based on the retrieved data, handling various states, including data availability, errors, and pending status.
Conclusion
Implementing APIs in Flutter apps is a crucial aspect of developing data-driven applications. The http package provides a straightforward and efficient way to interact with APIs and retrieve data. This guide has provided a step-by-step approach to implementing APIs in Flutter using the http package.
Enhance your Flutter app development with CodeTrade. We have a team of expert Flutter developers. Contact us today to hire Flutter developers and elevate your project to new heights.