Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Handling Errors with Dio/bloc Flutter

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 .

like image 955
alhussien aldali Avatar asked Dec 04 '25 16:12

alhussien aldali


1 Answers

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().

like image 110
Jay Dangar Avatar answered Dec 06 '25 15:12

Jay Dangar



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!