Published in · 6 min read · Apr 1, 2023
--
In Flutter there are various packages available for integrating APIs, such as Dio, Retrofit, HTTP, and many more. In this blog, we will try to learn about one of the most efficient packages for integrating APIs called Chopper.
Chopper is a package for making API calls in Flutter apps.
Chopper generates code that makes it easy to define API endpoints as Dart functions with strongly typed request and response bodies. It also supports interceptors for adding headers, logging requests and responses, and caching responses.
Chopper is built on top of the http
package, which means it supports all of the same HTTP methods (GET, POST, PUT, DELETE, etc.) and options as the http
package. However, Chopper makes it easier to write clean, organized code for making API calls in Flutter apps.
There are several reasons why you might want to use Chopper instead of other packages for making API calls in Flutter:
- Strongly-typed requests and responses: Chopper generates code that defines Dart classes for your API requests and responses, which makes it easy to work with data in a type-safe manner.
- Interceptors: Chopper supports interceptors, which can be used to add headers to requests, log requests and responses, and more.
- Easy to use: Chopper provides a simple and intuitive API for making API calls, which can make it easier for developers to get started and build their apps quickly.
Overall, Chopper is a powerful and flexible package for making API calls in Flutter, and it can be a great choice for developers who value strong typing, serialization, and ease of use.
Add the Chopper package to your pubspec.yaml
file:
dependencies:
chopper: ^<latest version>dev_dependencies:
build_runner: ^1.12.2
chopper_generator: ^<latest version>
Generate the Chopper code for your API
Chopper uses code generation to create API service classes based on the API specification. To generate the code, you’ll need to define an interface for your API using annotations from the chopper
package. Here's an example:
import 'package:chopper/chopper.dart';part 'AuthChopperService.chopper.dart';
@ChopperApi()
abstract class AuthChopperService extends ChopperService {
static AuthChopperService create({ChopperClient? client}) => _$AuthChopperService(client);
@Post(path:APIEndpoints.loginUrl)
Future<Response<LoginResponseEntity>> loginUser(
@body LoginRequest loginRequest);
@Post(path:APIEndpoints.registerUrl)
Future<Response<LoginResponseEntity>> registerUser(
@body RegisterUserRequest registerUser);
}
This code defines a Chopper service interface called AuthChopperService
using the @ChopperApi()
annotation.
The interface extends ChopperService
which provides a set of methods to interact with an API.
AuthChopperService
has a single method called loginUser
which is decorated with the @Post
annotation, indicating that it sends a HTTP POST request to the specified URL. The URL path is defined in the annotation with "login url"
.
The loginUser
method takes a single parameter loginRequest
, which is a Map<String,dynamic>
object that contains the login request data.
The return type of loginUser
is a Future<Response<LoginResponseEntity>>
. This means that the method returns a Future
object that will eventually contain a Response
object, which in turn contains a LoginResponseEntity
object.
LoginResponseEntity
is a custom Dart class that represents the response data for the login API call.
The static create
method is a factory method that creates an instance of AuthChopperService
with an optional ChopperClient
instance.
Finally, the AuthChopperService
interface is defined in a separate file called AuthChopperService.chopper.dart
, which is generated by Chopper when the app is built. This file contains the implementation of the service interface that makes the HTTP requests to the server. The implementation is generated based on the annotations and method signatures defined in the AuthChopperService
interface.
Once you’ve defined your API interface, you can generate the Chopper code by running the following command in your terminal:
flutter pub run build_runner build
This command will generate a new file called my_api_service.chopper.dart
that contains the Chopper service class for your API.
Create a Chopper client class
To use the Chopper services which we created, we have to get the instance of ChopperClient. For this we will use the following code.
class AppChopperClient {
late ChopperClient _client;
AppChopperClient() {
createChopperClient();
} T getChopperService<T extends ChopperService>() {
return _client.getService<T>();
}
void createChopperClient() {
_client = ChopperClient(
baseUrl: Uri.parse("<Base url>"),
services: [
AuthChopperService.create(),
],
interceptors: [
RequestLogger(),
ResponseLogger(),
ApplyHeaderInterceptor(),
],
converter: const JsonToTypeConverter(jsonConvertorMap: {
LoginResponseEntity: LoginResponseEntity.fromJson,
}),
errorConverter: const JsonToTypeConverter(
jsonConvertorMap: {GeneralErrorModel: GeneralErrorModel.fromJson}));
}
}
TheAppChopperClient
the class that uses the Chopper package in a Flutter app to create a Chopper client and Chopper service instances.
The class has a single private field _client
of type ChopperClient
, which is initialized in the constructor using the createChopperClient()
method. The method sets up the Chopper client with the following properties:
baseUrl
: A string that specifies the base URL for the API.services
: A list of Chopper service classes, which are defined using thecreate()
method of the corresponding service interface. In this example, there is only one service class,AuthChopperService
.interceptors
: A list of interceptors that can be used to modify the request or response before they are sent or received. In this example, there are three interceptors:RequestLogger
,ResponseLogger
, andApplyHeaderInterceptor
. We will look at each interceptor in detail in some other blog.converter
: An instance of aConverter
subclass that is used to serialize and deserialize JSON data. In this example, theJsonToTypeConverter
class used which is completely written by me, that maps JSON data to Dart classes using a map of converter functions.errorConverter
: An instance of aConverter
subclass that is used to convert error responses to Dart objects. In this example, theJsonToTypeConverter
class is used again, with a map that maps error responses toGeneralErrorModel
instances.
The class also defines a generic method getChopperService<T>()
that returns an instance of a Chopper service based on the type parameter T
. This method uses the _client
field to create and return an instance of the requested Chopper service.
Before we use it, we require to use some dependency injection method for initializing ChopperClient
and our AppChopperClient()
class. One of the way to achieve it is using Bindings in GetX.
import 'package:get/get.dart';class AuthBinding implements Bindings{
@override
void dependencies() {
Get.lazyPut(() => AppChopperClient());
}
}
Use the Chopper service to make API requests: Once you’ve created the Chopper client, you can use your Chopper service class to make API requests. Here’s an example:
final response = await Get.find<AppChopperClient>().getChopperService<AuthChopperService>ChopperClient>();
if (response.isSuccessful) {
final loginResponse = response.body;
// do something with the posts...
} else {
final loginError = response.error;
// handle the error...
}
This code uses the Chopper
package to make API calls in a Flutter app. We first get an instance of the AppChopperClient
class and call its getChopperService()
method to get an instance of the AuthChopperService
class, which defines API endpoints for authentication.
We call methods from the AuthChopperService
class to send requests to the server. The response is returned in a Response
object, which we check for success using the isSuccessful
property. We can access the response body using the body
property or the error using the error
property.
And that’s it! With these steps, you should be able to use the Chopper package to make API calls in your Flutter app.
To get code for three interceptors: RequestLogger
, ResponseLogger
, and ApplyHeaderInterceptor
and convertorJsonToTypeConverter
you can mail me on my email id: mustisid786@gmail.com
Thank you for reading! If you found this helpful, please give it a clap and share it with your friends and colleagues.