Skip to content

Instantly share code, notes, and snippets.

@DattatreyaReddy
Last active October 26, 2022 18:41
Show Gist options
  • Save DattatreyaReddy/5200e441ea85da3c1902fdb4032eaa66 to your computer and use it in GitHub Desktop.
Save DattatreyaReddy/5200e441ea85da3c1902fdb4032eaa66 to your computer and use it in GitHub Desktop.
DIo Client is a wrapper around Dio to support decoder with Compute (Threads)
import 'package:dio/dio.dart';
import 'package:flutter/foundation.dart';
import 'dio_error_util.dart';
typedef ResponseDecoderCallBack<DecoderType> = DecoderType Function(dynamic);
class DioClient {
final Dio dio;
DioClient(this.dio);
/// Handy method to make http GET request
///
///{@template dioClient}
/// - [ReturnType] is the expected return type.
/// - [DecoderType] is the return Type of decoder
///
/// for example:
/// 1. if [ReturnType] is User then [DecoderType] is User.
///
/// 2. if [ReturnType] is List\<User\> then [DecoderType] is User.
///{@endtemplate}
///
Future<Response<ReturnType?>> get<ReturnType, DecoderType>(
String url, {
Map<String, dynamic>? queryParameters,
ResponseDecoderCallBack<DecoderType>? decoder,
Options? options,
CancelToken? cancelToken,
ProgressCallback? onReceiveProgress,
}) =>
_handelDecoding<ReturnType, DecoderType>(
sendRequest: () => dio.get(
url,
queryParameters: queryParameters,
options: options,
cancelToken: cancelToken,
onReceiveProgress: onReceiveProgress,
),
decoder: decoder,
);
/// Handy method to make http POST request,
///
/// {@macro dioClient}
Future<Response<ReturnType?>> post<ReturnType, DecoderType>(
String url, {
dynamic data,
Map<String, dynamic>? queryParameters,
ResponseDecoderCallBack<DecoderType>? decoder,
Options? options,
CancelToken? cancelToken,
ProgressCallback? onSendProgress,
ProgressCallback? onReceiveProgress,
}) =>
_handelDecoding<ReturnType, DecoderType>(
sendRequest: () => dio.post(
url,
data: data,
queryParameters: queryParameters,
options: options,
cancelToken: cancelToken,
onSendProgress: onSendProgress,
onReceiveProgress: onReceiveProgress,
),
decoder: decoder,
);
/// Handy method to make http PATCH request,
///
/// {@macro dioClient}
Future<Response<ReturnType?>> patch<ReturnType, DecoderType>(
String url, {
dynamic data,
Map<String, dynamic>? queryParameters,
ResponseDecoderCallBack<DecoderType>? decoder,
Options? options,
CancelToken? cancelToken,
ProgressCallback? onSendProgress,
ProgressCallback? onReceiveProgress,
}) =>
_handelDecoding<ReturnType, DecoderType>(
sendRequest: () => dio.patch(
url,
data: data,
queryParameters: queryParameters,
options: options,
cancelToken: cancelToken,
onSendProgress: onSendProgress,
onReceiveProgress: onReceiveProgress,
),
decoder: decoder,
);
/// Handy method to make http PUT request,
///
/// {@macro dioClient}
Future<Response<ReturnType?>?> put<ReturnType, DecoderType>(
String url, {
data,
Map<String, dynamic>? queryParameters,
ResponseDecoderCallBack<DecoderType>? decoder,
Options? options,
CancelToken? cancelToken,
ProgressCallback? onSendProgress,
ProgressCallback? onReceiveProgress,
}) =>
_handelDecoding<ReturnType, DecoderType>(
sendRequest: () => dio.put(
url,
data: data,
queryParameters: queryParameters,
options: options,
cancelToken: cancelToken,
onSendProgress: onSendProgress,
onReceiveProgress: onReceiveProgress,
),
decoder: decoder,
);
/// Handy method to make http DELETE request,
///
/// {@macro dioClient}
Future<Response<ReturnType?>> delete<ReturnType, DecoderType>(
String url, {
data,
Map<String, dynamic>? queryParameters,
ResponseDecoderCallBack<DecoderType>? decoder,
Options? options,
CancelToken? cancelToken,
}) =>
_handelDecoding<ReturnType, DecoderType>(
sendRequest: () => dio.delete(
url,
data: data,
queryParameters: queryParameters,
options: options,
cancelToken: cancelToken,
),
decoder: decoder,
);
Future<Response<ReturnType?>> _handelDecoding<ReturnType, DecoderType>({
required Future<Response> Function() sendRequest,
ResponseDecoderCallBack<DecoderType>? decoder,
}) async {
try {
final Response response = await sendRequest();
ReturnType? result;
if (decoder != null) {
result = await _responseDecoder<ReturnType, DecoderType>(
responseData: response.data,
decoder: decoder,
);
} else if (response.data is ReturnType?) {
result = response.data;
}
return response.copyWith<ReturnType>(data: result);
} on DioError catch (e) {
if (kDebugMode) rethrow;
throw DioErrorUtil.handleError(e);
} catch (e) {
if (kDebugMode) rethrow;
throw "Unexpected error occurred";
}
}
Future<ReturnType?> _responseDecoder<ReturnType, DecoderType>({
required dynamic responseData,
required ResponseDecoderCallBack<DecoderType> decoder,
}) async {
if (responseData is List) {
final result = await compute<dynamic, List<DecoderType>>((message) {
final result = <DecoderType>[];
for (dynamic e in message) {
result.add((decoder(e)));
}
return result;
}, responseData);
return result as ReturnType?;
} else {
return await compute<Map<String, dynamic>, DecoderType>(
decoder,
responseData,
) as ReturnType?;
}
}
}
extension ResponseExtensions on Response {
Response<T?> copyWith<T>({
T? data,
Headers? headers,
RequestOptions? requestOptions,
bool? isRedirect,
int? statusCode,
String? statusMessage,
List<RedirectRecord>? redirects,
Map<String, dynamic>? extra,
}) =>
Response<T>(
data: data ?? (this.data is T? ? this.data : null),
headers: headers ?? this.headers,
requestOptions: requestOptions ?? this.requestOptions,
isRedirect: isRedirect ?? this.isRedirect,
statusCode: statusCode ?? this.statusCode,
statusMessage: statusMessage ?? this.statusMessage,
redirects: redirects ?? this.redirects,
extra: extra ?? this.extra,
);
}
import 'package:dio/dio.dart';
class DioErrorUtil {
// general methods:------------------------------------------------------------
/// Handles error for Dio Class
static String handleError(DioError? error) {
String errorDescription = "";
if (error is DioError) {
switch (error.type) {
case DioErrorType.cancel:
errorDescription = "Request cancelled";
break;
case DioErrorType.connectTimeout:
errorDescription = "Connection timeout";
break;
case DioErrorType.other:
errorDescription =
"Check your Internet Connection";
break;
case DioErrorType.receiveTimeout:
errorDescription = "Receive timeout";
break;
case DioErrorType.response:
errorDescription =
"Received invalid status code: ${error.response?.statusCode}";
break;
case DioErrorType.sendTimeout:
errorDescription = "Send timeout";
break;
}
} else {
errorDescription = "Unexpected error occurred";
}
return errorDescription;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment