Playx Network
Wrapper around Dio
that can perform API requests with better error handling and easily get the result of any API request.
Features
- Perform GET, POST, PUT,, and DELETE HTTP methods for retrieving from and sending data to a server.
- Better Error handling for API and
Dio
Errors with the ability to customize these errors. - Each request is wrapped by
NetworkResult
which returns whether success or failure of the API request. - No need to use try catch anymore as every request is handled.
- Logs network calls in a pretty, easy to read format
Installation
In pubspec.yaml
add these lines to dependencies
playx_network: ^0.2.0
Usage
We can use PlayxNetworkClient
to perform GET, POST, PUT,, and DELETE HTTP methods for retrieving from and sending data to a server.
To use it we need to :
-
Setup
PlayxNetworkClient
an configure it based on your needs. You should create only one instance of this network client to be used for the app depending on your use case.final PlayxNetworkClient _client = PlayxNetworkClient( //you can customize your dio options like base URL, connection time out. dio: Dio( BaseOptions( baseUrl: _baseUrl, connectTimeout: const Duration(seconds: 20), senTimeout: const Duration(seconds: 20), ), ), //If you want to attach a token to the client or add any custom headers to all requests. customHeaders: () async => { 'authorization': 'Bearer token' }, //Function that converts json error response from api to error message. // You should specify how to extract error message from the response. // defaults to as below: errorMapper: (json) { if (json.containsKey('message')) { return json['message'] as String? ; } return null; }, );
-
Now we can use the client to perform any GET, POST, PUT, and DELETE HTTP method.
For example we will perfrom a
GET
request that gets list of cats using this api :https://api.thecatapi.com/v1/images/search?limit=10
-
First create a model for the data returned from the api. It should contain a from json function that takes dynamic json and converts it to the model.
class Cat { String? id; String? url; num? width; num? height; Cat({ this.id, this.url, this.width, this.height,}); Cat.fromJson(dynamic json) { id = json['id']; url = json['url']; width = json['width']; height = json['height']; } Map<String, dynamic> toJson() { final map = <String, dynamic>{}; map['id'] = id; map['url'] = url; map['width'] = width; map['height'] = height; return map; }}
-
Perform the GET request :
//gets list of cats by getting cats endpoint. final result = await _client.getList(catsEndpoint, // pass your own queries. query: { 'limit': '10', }, // Pass the from json function that was created in the cat model. fromJson: Cat.fromJson);
-
Handle The request result :
result.when(success: (cats) { //Handles success here as it returns list of cats. }, error: (error) { //handle error here and display the error message. print("Error is : ${error.message}"); });
Just like that you can perform any GET, POST, PUT, and DELETE HTTP method and return it's result whether success or failure with better error handling.
-
Available Methods :
Here is all available methods of PlayxNetworkClient
:
Method | Description |
---|---|
get | sends a GET request to the given url and returns NetworkResult of Type T model. |
getList | sends a GET request to the given url and returns NetworkResult of List of Type T model. |
post | sends a POST request to the given url and returns NetworkResult of Type T model. |
postList | sends a POST request to the given url and returns NetworkResult of List of Type T model. |
put | sends a PUT request to the given url and returns NetworkResult of Type T model. |
putList | sends a PUT request to the given url and returns NetworkResult of List of Type T model. |
delete | sends a DELETE request to the given url and returns NetworkResult of Type T model. |
deleteList | sends a DELETE request to the given url and returns NetworkResult of List of Type T model. |
Error Message customization:
You can customize error message for the client and use your own messages.
-
Create a class that extends
ExceptionMessage
and overrides all messages with your own messages like that :class CustomExceptionMessage extends ExceptionMessage{ const CustomExceptionMessage(); @override String get badRequest => "Sorry, The API request is invalid or improperly formed."; @override String get conflict => "Sorry, The request wasn't completed due to a conflict."; @override String get defaultError => "Sorry, Something went wrong."; @override String get emptyResponse => "Sorry, Couldn't receive response from the server."; @override String get formatException => "Sorry, The request wasn't formatted correctly."; @override String get internalServerError => "Sorry, There is an internal server error"; @override String get noInternetConnection => "Sorry, There is no internet connection."; @override String get notAcceptable => "Sorry, The request is not acceptable"; @override String get notFound => "Sorry, The resource requested couldn't be found."; @override String get requestCancelled => "Sorry, The request has been canceled"; @override String get requestTimeout => "Sorry, The request has timed out."; @override String get sendTimeout => "Sorry, The request has send timeout in connection with API server"; @override String get serviceUnavailable => "Sorry, The service is unavailable"; @override String get unableToProcess => "Sorry, Couldn't process the data."; @override String get unauthorizedRequest => "Sorry, The request is unauthorized."; @override String get unexpectedError => "Sorry, Something went wrong."; }
- Configure
PlayxNetworkClient
to useCustomExceptionMessage
that you have created.
final PlayxNetworkClient _client = PlayxNetworkClient( exceptionMessages: const CustomExceptionMessage(), );
- Configure
Map Network Result
After getting the result from the API We can easily map the result to any type we want.
-
Here is an example that maps list of cats to list of image urls.
final NetworkResult<List<String?>> catImagesResult = result.map(success: (success) { final data = success.data; final images = data.map((e) => e.url).toList(); return NetworkResult.success(images); }, error: (error) { return NetworkResult<List<String?>>.error(error.error); });
-
We can also map result asynchronously using
mapAsync
like that :final NetworkResult<List<String?>> catImagesAsyncResult =await result.mapAsync(success: (success) async{ final data = success.data; final images = data.map((e) => e.url).toList(); return NetworkResult.success(images); }, error: (error)async { return NetworkResult<List<String?>>.error(error.error); });
Logging
The package uses pretty_dio_logger
pacakge to log dio requests.
How it looks like
VS Code
Android studio
You can customize what is printed or whether it's enabled or not like this:
final PlayxNetworkClient _client = PlayxNetworkClient(
//attach logger to the client to print API requests, works only on debug mode.
attachLoggerOnDebug: true,
// You can customize the logger settings.
logSettings: const LoggerSettings(
responseBody: true,
request = true,
requestHeader = true,
requestBody = true,
responseHeader = false,
error = true,
maxWidth = 90,
compact = true,
),
);
See Also:
Playx : Playx eco system helps with redundant features , less code , more productivity , better organizing.
Playx_theme :Multi theme features for flutter apps from playx eco system.
Playx_core :Core package for playx eco system contains shared classes and utilities.