J'utilise BLOC Pattern, donc ma question est de savoir comment renvoyer une erreur après une requête HTTP. Supposons que si l'API renvoie 200 en tant que code d'état, je peux retourner le modèle particulier que j'ai mentionné s'il y a une erreur de retour de l'API comme 302, 404 401 ... ainsi de suite alors comment gérer cela et retourner l'interface utilisateur pour afficher la Message d'erreur

Future<SampleModel> getSomeDetails(String ID) async {
    var response =
    await http.get(someURL,
        headers: {'Content-type': 'application/x-www-form-urlencoded',});
    if (response.statusCode == 200) {
      return SampleModel.fromJson(json.decode(response.body));
    } else {
      throw Exception('Failed to load post');// return the error to UI
    }
  }

PS: j'utilise également le modèle d'observateur

0
Android 4 nov. 2019 à 08:04

3 réponses

Parce que vous utilisez bloc, vous avez probablement une sorte de flux auquel vous ajoutez des données:

StreamController<int> data = new StreamController<int>();

Et vous utilisez probablement StreamBuilder pour écouter les événements sur ce flux et afficher les données. Vous pouvez également écouter les erreurs sur le flux:

StreamBuilder<int>(
  builder: (context, snapshot) {
    if (snapshot.hasError) {
      // Show error message
      return Text('An error occured');
    } else if (snapshot.hasData) {
      // Show data
      return Text('${snapshot.data}');
    }

    // No data, show loader
    return CircularProgressIndicator();
  },
  stream: data.stream,
),

Vous pouvez donc simplement une erreur dans le flux:

// Adding an error to the stream
data.addError('Failed to load post');
1
Igor Kharakhordin 4 nov. 2019 à 05:47

J'utilise mon propre mécanisme d'appel API qui est donné ci-dessous en ce que vous pouvez gérer tous les types d'exceptions.

api_handler.dart

import 'dart:async';
import 'dart:convert';

import 'package:connectivity/connectivity.dart';
import 'package:package_name/base/api/api_exception.dart';
import 'package:package_name/utils/app_constatns.dart';
import 'package:package_name/utils/log_utils.dart';
import 'package:package_name/utils/preference_utils.dart';
import 'package:package_name/utils/strings.dart';
import 'package:http/http.dart' as http;

class ApiHandler {
  // next three lines makes this class a Singleton
  static ApiHandler _instance = new ApiHandler.internal();
  final JsonDecoder _decoder = new JsonDecoder();

  ApiHandler.internal();

  factory ApiHandler() => _instance;

  Future<bool> isInternetConnected() async {
    var connectivityResult = await (Connectivity().checkConnectivity());
    if (connectivityResult == ConnectivityResult.mobile ||
        connectivityResult == ConnectivityResult.wifi) {
      return true;
    }
    return false;
  }

  Future<dynamic> get(String url) async {
    LogUtils.d("====URL GET Call:   $url");
    String token = PreferenceUtils.getString(AppConstants.LOGGED_IN);

    // ignore: unrelated_type_equality_checks
    var isConnected = await isInternetConnected();
    if (isConnected != true) {
      return Future.error(ApiException(Strings.internetNotConnected));
    }
    return http.get(url, headers: {"Authorization": "Bearer $token"}).then(
        (http.Response response) {
      final int statusCode = response.statusCode;
      LogUtils.d("====response ${response.body.toString()}");

      if (statusCode < 200 || statusCode >= 400 || json == null) {
        throw new ApiException(jsonDecode(response.body)["message"]);
      }
      return _decoder.convert(response.body);
    });
  }

  Future<dynamic> post(String url, {body, encoding}) async {
    LogUtils.d("====URL POST Call:   $url");
    LogUtils.d("====body :   $body");
    String token = PreferenceUtils.getString(AppConstants.LOGGED_IN);
    var isConnected = await isInternetConnected();
    if (isConnected != true) {
      return Future.error(ApiException(Strings.internetNotConnected));
    }

    return http.post(url,
            body: json.encode(body),
            headers: { 'Content-type': 'application/json',
              'Accept': 'application/json',
              "Authorization": "Bearer $token"},
            encoding: encoding)
            .then((http.Response response) {
      final int statusCode = response.statusCode;
      LogUtils.d("====responseBody ${response.body.toString()}");
      LogUtils.d("====responseStatusCode ${response.statusCode}");

      if (statusCode < 200 || statusCode >= 400 || json == null) {
        throw new ApiException(jsonDecode(response.body)["message"]);
      }
      return _decoder.convert(response.body);
    });
  }
}

api_exception.dart

class ApiException implements Exception {
  String errorMsg = "Server not respond";

  ApiException(String error) {
    this.errorMsg = error ?? "Server not respond";
  }
}

api_manager.dart

import 'dart:convert';
import 'dart:io';

import 'package:flutter_my_recipes/utils/log_utils.dart';
import 'package:flutter_my_recipes/utils/preference_utils.dart';
import 'package:http/http.dart' as http;
import 'package:http_parser/http_parser.dart';

import 'api_handler.dart';

class ApiManager {
  // next three lines makes this class a Singleton
  static ApiManager _instance = new ApiManager.internal();

  ApiManager.internal();

  factory ApiManager() => _instance;

  static ApiHandler _handler;

  static void init() {
    _handler = new ApiHandler();
  }

  static Future<LoginRes> loginApi(Map<String, dynamic> json) {
    return _handler.post(UrlConstants.LOGIN_URL, body: json).then((res) {
      return LoginRes.fromJson(res);
    });
  }
}

Exemple d'appel API: -

void loginApiCall(BuildContext context, LoginReq _signInReq) {
    ApiManager.loginApi(_signInReq.toJson()).then((signInResponse) {
      notifyListeners();
      print("===Success $signInResponse");
      PreferenceUtils.setString(
          AppConstants.USERDATA, JsonCodec().encode(signInResponse.toJson()));
      PreferenceUtils.setString(AppConstants.LOGGED_IN, signInResponse.token);
      isLoading = false;
      Navigation.pushAndRemoveUntil(context, Screens.HOME);
    }).catchError((onError) {
      isLoading = false;
      notifyListeners();
      print("===onError $onError");
      ProcessDialog.closeLoadingDialog();
      Toast.show(onError.errorMsg, context, duration: 2);
    });
  }

Vous devez appeler la méthode d'initialisation ApiManager dans le fichier main.dart afin de pouvoir utiliser l'instance Apimanager partout dans l'application.

0
Ankit Mahadik 4 nov. 2019 à 05:38

Vous pouvez retourner:

Future.error("Error message").

Ensuite, vous pouvez faire quelque chose comme ceci:

getSomeDetails("id")
    .then((value) => print('Value: $value'))
    .catchError((error) => print('Error: $error'));

ou

FutureBuilder(
  future: getSomeDetails("id"),
  builder: (context, snapshot) {
    if (snapshot.hasData) {
      return Text('Value: ${snapshot.data}');
    } else if (snapshot.hasError) {
      return Text('Error: ${snapshot.error}');
    }
    return Text('Loading...');
  },
)
1
Pablo Barrera 4 nov. 2019 à 05:52