network<T> method
Future<T?>
network<T>({
- required dynamic request(
- Dio api
- dynamic handleSuccess(
- Response response
- dynamic handleFailure(
- DioException error
- String? bearerToken,
- String? baseUrl,
- bool useUndefinedResponse = true,
- bool shouldRetry = true,
- bool? shouldSetAuthHeaders,
- int? retry,
- Duration? retryDelay,
- bool retryIf(
- DioException dioException
- Duration? connectionTimeout,
- Duration? receiveTimeout,
- Duration? sendTimeout,
- Duration? cacheDuration,
- String? cacheKey,
- Map<
String, dynamic> ? headers,
Networking class to handle API requests
Use the request
callback to call an API
handleSuccess
overrides the response on a successful status code
handleFailure
overrides the response on a failure
Usage: Future<List
Implementation
Future<T?> network<T>(
{required Function(Dio api) request,
Function(Response response)? handleSuccess,
Function(DioException error)? handleFailure,
String? bearerToken,
String? baseUrl,
bool useUndefinedResponse = true,
bool shouldRetry = true,
bool? shouldSetAuthHeaders,
int? retry,
Duration? retryDelay,
bool Function(DioException dioException)? retryIf,
Duration? connectionTimeout,
Duration? receiveTimeout,
Duration? sendTimeout,
Duration? cacheDuration,
String? cacheKey,
Map<String, dynamic>? headers}) async {
headers ??= {};
try {
Map<String, dynamic> oldHeader = _api.options.headers;
Map<String, dynamic> newValuesToAddToHeader = {};
if (headers.isNotEmpty) {
for (var header in headers.entries) {
if (!oldHeader.containsKey(header.key)) {
newValuesToAddToHeader.addAll({header.key: header.value});
}
}
}
if (await shouldRefreshToken()) {
await refreshToken(Dio());
}
if (bearerToken != null) {
newValuesToAddToHeader.addAll({"Authorization": "Bearer $bearerToken"});
} else {
if ((shouldSetAuthHeaders ?? this.shouldSetAuthHeaders) == true) {
newValuesToAddToHeader.addAll(await setAuthHeaders(headers));
}
}
_api.options.headers.addAll(newValuesToAddToHeader);
String oldBaseUrl = _api.options.baseUrl;
if (baseUrl != null) {
_api.options.baseUrl = baseUrl;
}
if (connectionTimeout != null) {
_api.options.connectTimeout = connectionTimeout;
}
if (receiveTimeout != null) {
_api.options.receiveTimeout = receiveTimeout;
}
if (sendTimeout != null) {
_api.options.sendTimeout = sendTimeout;
}
Response? response;
Duration? cacheDurationRequest = cacheDuration;
cacheDurationRequest ??= _cacheDuration;
String? cacheKeyRequest = cacheKey;
cacheKeyRequest ??= _cacheKey;
if (cacheDurationRequest != null || cacheKeyRequest != null) {
assert(cacheDurationRequest != null, 'Cache duration is required');
assert(cacheKeyRequest != null, 'Cache key is required');
int inSeconds = cacheDurationRequest?.inSeconds ?? 60;
bool cacheHit = true;
Map responseMap = await ny_cache
.cache()
.saveRemember(cacheKeyRequest!, inSeconds, () async {
cacheHit = false;
Response requestData = await request(_api);
return {
'requestOptions': {
'path': requestData.requestOptions.path,
'method': requestData.requestOptions.method,
'baseUrl': requestData.requestOptions.baseUrl,
},
'statusCode': requestData.statusCode,
'statusMessage': requestData.statusMessage,
'data': requestData.data,
};
});
response = Response(
requestOptions: RequestOptions(
path: responseMap['requestOptions']['path'],
method: responseMap['requestOptions']['method'],
baseUrl: responseMap['requestOptions']['baseUrl'],
),
statusCode: responseMap['statusCode'],
statusMessage: responseMap['statusMessage'],
data: responseMap['data'],
);
if (cacheHit) {
printDebug('');
printDebug('╔╣ ${response.requestOptions.uri}');
printDebug('║ Cache ${cacheHit ? 'hit' : 'miss'}: $cacheKeyRequest');
printDebug('║ Status: ${response.statusCode}');
printDebug('╚╣ Response');
printDebug(response.data);
} else {
printDebug('Cached response $cacheKeyRequest');
}
} else {
response = await request(_api);
}
_api.options.headers = oldHeader; // reset headers
_api.options.baseUrl = oldBaseUrl; // reset base url
_api.options.queryParameters = {}; // reset query parameters
dynamic data = handleResponse<T>(response!, handleSuccess: handleSuccess);
if (data != T && useUndefinedResponse) {
onUndefinedResponse(data, response, _context);
}
if (_onSuccessEvent != null) {
_onSuccessEvent!(response, data);
}
_context = null;
return data;
} on DioException catch (dioException) {
int nyRetries = retry ?? this.retry;
Duration nyRetryDelay = retryDelay ?? this.retryDelay;
bool Function(DioException dioException)? retryIfFinal = this.retryIf;
if (retryIf != null) {
retryIfFinal = retryIf;
}
if (retryIfFinal != null) {
shouldRetry = retryIfFinal(dioException);
}
if (_retrying == false && shouldRetry == true && nyRetries > 0) {
_retrying = true;
for (var i = 0; i < nyRetries; i++) {
await Future.delayed(nyRetryDelay);
NyLogger.debug("[${i + 1}] Retrying request...");
dynamic response = await network(
request: request,
handleSuccess: handleSuccess,
handleFailure: handleFailure,
bearerToken: bearerToken,
baseUrl: baseUrl,
useUndefinedResponse: useUndefinedResponse,
headers: headers,
shouldRetry: false,
);
if (response != null) {
_retrying = false;
return response;
}
}
_retrying = false;
}
NyLogger.error(dioException.toString());
error(dioException);
if (_context != null) {
displayError(dioException, _context!);
}
if (handleFailure != null) {
return handleFailure(dioException);
}
if (_onErrorEvent != null) {
_onErrorEvent!(dioException);
}
return null;
} on Exception catch (e) {
NyLogger.error(e.toString());
return null;
}
}