playx_network 1.0.0 copy "playx_network: ^1.0.0" to clipboard
playx_network: ^1.0.0 copied to clipboard

playx_network is a Wrapper around Dio that can perform api request with better error handling and easily get the result of any api request.

Playx Network #

pub package

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, PATCH, 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.7.0


## Usage

We can use `PlayxNetworkClient`  to perform GET, POST, PUT, PATCH, 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.
   ```dart
   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),
          sendTimeout: 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.
patch sends a PATCH request to the given url and returns NetworkResult of Type [T] model.
patchList sends a PATCH request to the given url and returns NetworkResult of List of Type [T] model.

Nested JSON Key Extraction #

You can extract nested JSON values directly from the response before parsing using dot-notation with the dataKey parameter. This is useful when you want to target a specific field in a large JSON structure without mapping the outer layers.

final result = await _client.get(
  'forecast',
  query: {
    'latitude': '30.04',
    'longitude': '31.23',
    'current_weather': 'true',
  },
  // Extract 'current_weather' directly from the response
  dataKey: 'current_weather',
  fromJson: CurrentWeather.fromJson,
);

Smart Request Cancellation #

Manage and cancel multiple requests easily using cancelTag. By default, providing a cancelTag will automatically cancel any previous pending requests with the same tag (cancelOld: true).

// Subsequent calls with the same tag will cancel previous ones automatically
networkClient.getList(
  '/search?q=query',
  cancelTag: 'search_request',
  fromJson: Cat.fromJson,
);

// You can also cancel requests manually
networkClient.cancelRequestsByTag('search_request');

Additionally, if a request is canceled while JSON mapping is occurring in an isolate, the mapping process itself is also terminated to save resources.

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.";
        }
    
    • ConfigurePlayxNetworkClient to use CustomExceptionMessage that you have created.
    final PlayxNetworkClient _client = PlayxNetworkClient(
       exceptionMessages: const CustomExceptionMessage(),
     );
    

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

Request Example Error Example

Android studio #

Response Example

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.

2
likes
160
points
2.62k
downloads

Documentation

API reference

Publisher

verified publisherplayx.sourcya.io

Weekly Downloads

playx_network is a Wrapper around Dio that can perform api request with better error handling and easily get the result of any api request.

Homepage
Repository (GitHub)
View/report issues

Topics

#playx #dio #network #api

License

MIT (license)

Dependencies

dio, dio_smart_retry, dio_web_adapter, flutter, playx_core, sentry_dio, talker, talker_dio_logger

More

Packages that depend on playx_network