Last active
July 3, 2022 17:44
-
-
Save arafaysaleem/ddd1667aba480ca14c68c6107ff1704a to your computer and use it in GitHub Desktop.
Custom Exception for Networking Layer
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
// ignore_for_file: constant_identifier_names | |
import 'package:dio/dio.dart'; | |
import 'package:flutter/foundation.dart'; | |
/// An enum that holds names for our custom exceptions. | |
enum _ExceptionType { | |
/// The exception for an expired bearer token. | |
TokenExpiredException, | |
/// The exception for a prematurely cancelled request. | |
CancelException, | |
/// The exception for a failed connection attempt. | |
ConnectTimeoutException, | |
/// The exception for failing to send a request. | |
SendTimeoutException, | |
/// The exception for failing to receive a response. | |
ReceiveTimeoutException, | |
/// The exception for no internet connectivity. | |
SocketException, | |
/// A better name for the socket exception. | |
FetchDataException, | |
/// The exception for an incorrect parameter in a request/response. | |
FormatException, | |
/// The exception for an unknown type of failure. | |
UnrecognizedException, | |
/// The exception for an unknown exception from the api. | |
ApiException, | |
/// The exception for any parsing failure encountered during | |
/// serialization/deserialization of a request. | |
SerializationException, | |
} | |
class CustomException implements Exception { | |
final String name, message; | |
final String? code; | |
final int? statusCode; | |
final _ExceptionType exceptionType; | |
CustomException({ | |
this.code, | |
int? statusCode, | |
required this.message, | |
this.exceptionType = _ExceptionType.ApiException, | |
}) : statusCode = statusCode ?? 500, | |
name = exceptionType.name; | |
factory CustomException.fromDioException(Exception error) { | |
try { | |
if (error is DioError) { | |
switch (error.type) { | |
case DioErrorType.cancel: | |
return CustomException( | |
exceptionType: _ExceptionType.CancelException, | |
statusCode: error.response?.statusCode, | |
message: 'Request cancelled prematurely', | |
); | |
case DioErrorType.connectTimeout: | |
return CustomException( | |
exceptionType: _ExceptionType.ConnectTimeoutException, | |
statusCode: error.response?.statusCode, | |
message: 'Connection not established', | |
); | |
case DioErrorType.sendTimeout: | |
return CustomException( | |
exceptionType: _ExceptionType.SendTimeoutException, | |
statusCode: error.response?.statusCode, | |
message: 'Failed to send', | |
); | |
case DioErrorType.receiveTimeout: | |
return CustomException( | |
exceptionType: _ExceptionType.ReceiveTimeoutException, | |
statusCode: error.response?.statusCode, | |
message: 'Failed to receive', | |
); | |
case DioErrorType.response: | |
case DioErrorType.other: | |
if (error.message.contains(_ExceptionType.SocketException.name)) { | |
return CustomException( | |
exceptionType: _ExceptionType.FetchDataException, | |
statusCode: error.response?.statusCode, | |
message: 'No internet connectivity', | |
); | |
} | |
if (error.response?.data['headers']['code'] == null) { | |
return CustomException( | |
exceptionType: _ExceptionType.UnrecognizedException, | |
statusCode: error.response?.statusCode, | |
message: error.response?.statusMessage ?? 'Unknown', | |
); | |
} | |
final name = error.response?.data['headers']['code'] as String; | |
final message = | |
error.response?.data['headers']['message'] as String; | |
if (name == _ExceptionType.TokenExpiredException.name) { | |
return CustomException( | |
exceptionType: _ExceptionType.TokenExpiredException, | |
code: name, | |
statusCode: error.response?.statusCode, | |
message: message, | |
); | |
} | |
return CustomException( | |
message: message, | |
code: name, | |
statusCode: error.response?.statusCode, | |
); | |
} | |
} else { | |
return CustomException( | |
exceptionType: _ExceptionType.UnrecognizedException, | |
message: 'Error unrecognized', | |
); | |
} | |
} on FormatException catch (e) { | |
return CustomException( | |
exceptionType: _ExceptionType.FormatException, | |
message: e.message, | |
); | |
} on Exception catch (_) { | |
return CustomException( | |
exceptionType: _ExceptionType.UnrecognizedException, | |
message: 'Error unrecognized', | |
); | |
} | |
} | |
factory CustomException.fromParsingException(Exception error) { | |
// TODO(arafaysaleem): add logging to print stack trace | |
debugPrint('$error'); | |
return CustomException( | |
exceptionType: _ExceptionType.SerializationException, | |
message: 'Failed to parse network response to model or vice versa', | |
); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment