Last active
July 3, 2022 15:14
-
-
Save arafaysaleem/90fd380f972c2392ca5e0caa27910cbb to your computer and use it in GitHub Desktop.
Generic Dio Service Wrapper
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import 'dart:async'; | |
import 'package:dio/dio.dart'; | |
import 'package:dio_cache_interceptor/dio_cache_interceptor.dart'; | |
// Exceptions | |
import './custom_exception.dart'; | |
// Helpers | |
import '../../helpers/typedefs.dart'; | |
// Models | |
import 'response_model.dart'; | |
/// A service class that wraps the [Dio] instance and provides methods for | |
/// basic network requests. | |
class DioService { | |
/// An instance of [Dio] for executing network requests. | |
final Dio _dio; | |
/// A set of cache options to be used for each request | |
final CacheOptions? globalCacheOptions; | |
/// An instance of [CancelToken] used to pre-maturely cancel | |
/// network requests. | |
final CancelToken _cancelToken; | |
/// A public constructor that is used to create a Dio service and initialize | |
/// the underlying [Dio] client. | |
/// | |
/// * [interceptors]: An [Iterable] for attaching custom | |
/// [Interceptor]s to the underlying [_dio] client. | |
/// * [httpClientAdapter]: Replaces the underlying [HttpClientAdapter] with | |
/// this custom one. | |
DioService({ | |
required Dio dioClient, | |
this.globalCacheOptions, | |
Iterable<Interceptor>? interceptors, | |
HttpClientAdapter? httpClientAdapter, | |
}) : _dio = dioClient, | |
_cancelToken = CancelToken() { | |
if (interceptors != null) _dio.interceptors.addAll(interceptors); | |
if (httpClientAdapter != null) _dio.httpClientAdapter = httpClientAdapter; | |
} | |
/// This method invokes the [cancel()] method on either the input | |
/// [cancelToken] or internal [_cancelToken] to pre-maturely end all | |
/// requests attached to this token. | |
void cancelRequests({CancelToken? cancelToken}) { | |
if (cancelToken == null) { | |
_cancelToken.cancel('Cancelled'); | |
} else { | |
cancelToken.cancel(); | |
} | |
} | |
/// This method sends a `GET` request to the [endpoint], **decodes** | |
/// the response and returns a parsed [ResponseModel] with a body of type [R]. | |
/// | |
/// Any errors encountered during the request are caught and a custom | |
/// [CustomException] is thrown. | |
/// | |
/// [queryParams] holds any query parameters for the request. | |
/// | |
/// [cancelToken] is used to cancel the request pre-maturely. If null, | |
/// the **default** [cancelToken] inside [DioService] is used. | |
/// | |
/// [cacheOptions] are special cache instructions that can merge and override | |
/// the [globalCacheOptions]. | |
/// | |
/// [options] are special instructions that can be merged with the request. | |
Future<ResponseModel<R>> get<R>({ | |
required String endpoint, | |
JSON? queryParams, | |
Options? options, | |
CacheOptions? cacheOptions, | |
CancelToken? cancelToken, | |
}) async { | |
final response = await _dio.get<JSON>( | |
endpoint, | |
queryParameters: queryParams, | |
options: _mergeDioAndCacheOptions( | |
dioOptions: options, | |
cacheOptions: cacheOptions, | |
), | |
cancelToken: cancelToken ?? _cancelToken, | |
); | |
return ResponseModel<R>.fromJson(response.data!); | |
} | |
/// This method sends a `POST` request to the [endpoint], **decodes** | |
/// the response and returns a parsed [ResponseModel] with a body of type [R]. | |
/// | |
/// Any errors encountered during the request are caught and a custom | |
/// [CustomException] is thrown. | |
/// | |
/// The [data] contains body for the request. | |
/// | |
/// [cancelToken] is used to cancel the request pre-maturely. If null, | |
/// the **default** [cancelToken] inside [DioService] is used. | |
/// | |
/// [options] are special instructions that can be merged with the request. | |
Future<ResponseModel<R>> post<R>({ | |
required String endpoint, | |
JSON? data, | |
Options? options, | |
CancelToken? cancelToken, | |
}) async { | |
final response = await _dio.post<JSON>( | |
endpoint, | |
data: data, | |
options: options, | |
cancelToken: cancelToken ?? _cancelToken, | |
); | |
return ResponseModel<R>.fromJson(response.data!); | |
} | |
/// This method sends a `PATCH` request to the [endpoint], **decodes** | |
/// the response and returns a parsed [ResponseModel] with a body of type [R]. | |
/// | |
/// Any errors encountered during the request are caught and a custom | |
/// [CustomException] is thrown. | |
/// | |
/// The [data] contains body for the request. | |
/// | |
/// [cancelToken] is used to cancel the request pre-maturely. If null, | |
/// the **default** [cancelToken] inside [DioService] is used. | |
/// | |
/// [options] are special instructions that can be merged with the request. | |
Future<ResponseModel<R>> patch<R>({ | |
required String endpoint, | |
JSON? data, | |
Options? options, | |
CancelToken? cancelToken, | |
}) async { | |
final response = await _dio.patch<JSON>( | |
endpoint, | |
data: data, | |
options: options, | |
cancelToken: cancelToken ?? _cancelToken, | |
); | |
return ResponseModel<R>.fromJson(response.data!); | |
} | |
/// This method sends a `DELETE` request to the [endpoint], **decodes** | |
/// the response and returns a parsed [ResponseModel] with a body of type [R]. | |
/// | |
/// Any errors encountered during the request are caught and a custom | |
/// [CustomException] is thrown. | |
/// | |
/// The [data] contains body for the request. | |
/// | |
/// [cancelToken] is used to cancel the request pre-maturely. If null, | |
/// the **default** [cancelToken] inside [DioService] is used. | |
/// | |
/// [options] are special instructions that can be merged with the request. | |
Future<ResponseModel<R>> delete<R>({ | |
required String endpoint, | |
JSON? data, | |
Options? options, | |
CancelToken? cancelToken, | |
}) async { | |
final response = await _dio.delete<JSON>( | |
endpoint, | |
data: data, | |
options: options, | |
cancelToken: cancelToken ?? _cancelToken, | |
); | |
return ResponseModel<R>.fromJson(response.data!); | |
} | |
/// A utility method used to merge together [Options] | |
/// and [CacheOptions]. | |
/// | |
/// Returns an [Options] object with [CacheOptions] stored | |
/// in the [options.extra] key. | |
Options? _mergeDioAndCacheOptions({ | |
Options? dioOptions, | |
CacheOptions? cacheOptions, | |
}) { | |
if (dioOptions == null && cacheOptions == null) { | |
return null; | |
} else if (dioOptions == null && cacheOptions != null) { | |
return cacheOptions.toOptions(); | |
} else if (dioOptions != null && cacheOptions == null) { | |
return dioOptions; | |
} | |
final _cacheOptionsMap = cacheOptions!.toExtra(); | |
final options = dioOptions!.copyWith( | |
extra: <String, dynamic>{...dioOptions.extra!, ..._cacheOptionsMap}, | |
); | |
return options; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment