Reputation: 139
I need a good way to handle errors while I'm Using Dio requests. Can I do it in one class and pass the dio request throw it ? and it should return a response with the error .
Upvotes: 3
Views: 1318
Reputation: 3469
I am posting my generalized network bloc here, which can be reused any number of time, any where. also, It uses dio using API repository , exceptional and error handling.
class NetworkBloc extends Bloc<NetworkEvent, NetworkState> {
NetworkBloc() : super(NetworkRequestInitial());
@override
Stream<NetworkState> mapEventToState(
NetworkEvent event,
) async* {
yield NetworkRequestInitiated();
if (event is NetworkCallEvent) {
RequestType requestType = event.requestType;
if (requestType == RequestType.GET) {
yield* fetchData(event);
} else if (requestType == RequestType.POST) {
yield* uploadDataAndStoreResult(event);
}
}
}
Stream<NetworkState> fetchData(NetworkCallEvent event) async* {
Response response;
try {
yield NetworkRequestLoading();
response =
await event.apiRepository.sendGetRequest(event.url, event.request);
if (response.statusCode == 200) {
yield NetworkRequestLoaded(response: response);
} else {
Map jsonResponse = jsonDecode(response.data);
yield NetworkRequestFailure(message: jsonResponse['message']);
}
} catch (e) {
yield NetworkRequestFailure(
message: NetworkUtils.getErrorMessageAccordingToError(e));
}
}
Stream<NetworkState> uploadDataAndStoreResult(NetworkCallEvent event) async* {
Response response;
try {
yield NetworkRequestLoading();
if (event.request != null) {
if (event.isHeadersNeeded) {
response = await event.apiRepository.sendPostRequestWithHeader(
event.url,
request: event.request,
);
} else {
response = await event.apiRepository.sendPostRequest(
event.url,
event.request,
);
}
} else {
response = await event.apiRepository
.sendPostRequestWithoutBodyParameters(event.url);
}
if (response.statusCode == 200) {
saveDataAccordingToCacheMechanism(event, response);
yield NetworkRequestLoaded(response: response);
} else {
Map jsonResponse = jsonDecode(response.data);
yield NetworkRequestFailure(message: jsonResponse['message']);
}
} catch (e) {
yield NetworkRequestFailure(
message: NetworkUtils.getErrorMessageAccordingToError(e));
}
}
void saveDataAccordingToCacheMechanism(
NetworkCallEvent event, Response response) async {
if (event.cacheMechanism == CacheMechanism.SharePreferences) {
Hive.box(ConstUtils.dbName)
.put(event.keyForSharedPreferences, response.data.toString());
} else if (event.cacheMechanism == CacheMechanism.Database) {}
}
}
I am also adding states and events to make it more easy to understand.
class NetworkCallEvent extends NetworkEvent {
final String request;
final dynamic url;
final RequestType requestType;
final CacheMechanism cacheMechanism;
final String keyForSharedPreferences;
final APIRepository apiRepository;
final bool isHeadersNeeded;
NetworkCallEvent(
{@required this.url,
this.request,
this.isHeadersNeeded = false,
@required this.requestType,
@required this.apiRepository,
@required this.cacheMechanism,
this.keyForSharedPreferences});
@override
List<Object> get props => [
this.url,
this.request,
this.requestType,
this.cacheMechanism,
this.keyForSharedPreferences,
this.apiRepository
];
}
Network_states:
class NetworkRequestInitial extends NetworkState {}
class NetworkRequestInitiated extends NetworkState {}
class NetworkRequestLoading extends NetworkState {}
class NetworkRequestLoaded extends NetworkState {
final dynamic response;
NetworkRequestLoaded({this.response});
@override
List<Object> get props => [this.response];
}
class NetworkRequestFailure extends NetworkState {
final String message;
NetworkRequestFailure({this.message});
@override
List<Object> get props => [this.message];
}
You can easily send request in JSON and get Response in dynamic, which you can convert to appropriate object using json.decode()
.
Upvotes: 1