Copyright notice: This article is the blogger’s original article, reproduced please indicate the source!

Web requests are a very important part of every project, and there are many ways to build Flutter. Here I use the DIO library, which has a very complete API. I won’t go into details about how to use this library. In order to make it more convenient for us to use, I make a layer of encapsulation, which will contain various forms submission, JSON submission, etc., and also contains a unified login exception monitoring, and a unified data processing and unified exception processing. As always, we’ll see in the code below:

class NetUtil {
  static final debug = false; static BuildContext context = null; /// Server path static final host ='http://xxxxxxxx';
  static final baseUrl = host + '/api/'; Static final Dio _dio = new Dio(new Options(method:"get",
      baseUrl: baseUrl,
      connectTimeout: 5000,
      receiveTimeout: 5000,
      followRedirects: true)); // Set the proxy to capture packets for interface adjustment // static voidsetProxy() {
//    (_dio.httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate = (client) {
//      // config the http client
//      client.findProxy = (uri) {
//        //proxy all request to localhost:8888
//        return "PROXY localhost:8888";
//      };
//      // you can also create a new HttpClient to dio
//      // return new HttpClient();
//    };
//  }


  static String token;

  static final LogicError unknowError = LogicError(-1, "Unknown exception");

  static Future<Map<String, dynamic>> getJson<T>(
          String uri, Map<String, dynamic> paras) =>
      _httpJson("get", uri, data: paras).then(logicalErrorTransform);

  static Future<Map<String, dynamic>> getForm<T>(
          String uri, Map<String, dynamic> paras) =>
      _httpJson("get", uri, data: paras, dataIsJson: false) .then(logicalErrorTransform); PostForm <T>(String URI, Map<String, dynamic> paras) => _httpJson("post", uri, data: paras, dataIsJson: false) .then(logicalErrorTransform); Static Future<Map<String, dynamic>> postJson(String uri, Map<String, dynamic> body) => _httpJson("post", uri, data: body).then(logicalErrorTransform);

  static Future<Map<String, dynamic>> deleteJson<T>(
          String uri, Map<String, dynamic> body) =>
      _httpJson("delete", uri, data: body).then(logicalErrorTransform); Put static Future<Map<String, dynamic>> putJson<T>(String URI, Map<String, dynamic> body) => _httpJson("put", uri, data: body).then(logicalErrorTransform); // put static Future<Map<String, dynamic>> putForm<T>(String URI, Map<String, dynamic> body) => _httpJson("put", uri, data: body, dataIsJson: false) .then(logicalErrorTransform); Static Future<T> putFile<T>(String URI, String filePath) { var name = filePath.substring(filePath.lastIndexOf("/") + 1, filePath.length);
    var suffix = name.substring(name.lastIndexOf(".") + 1, name.length);
    FormData formData = new FormData.from({
      "multipartFile": new UploadFileInfo(new File(filePath), name,
          contentType: ContentType.parse("image/$suffix"))}); var enToken = token == null ?"" : Uri.encodeFull(token);
    return _dio
        .put<Map<String, dynamic>>("$uri? token=$enToken", data: formData)
        .then(logicalErrorTransform);
  }

  static Future<Response<Map<String, dynamic>>> _httpJson(
      String method, String uri,
      {Map<String, dynamic> data, bool dataIsJson = true}) {
    var enToken = token == null ? "": Uri.encodeFull(token); /// if the method is get, the parameters are concatenatedif (method == "get") {
      dataIsJson = false;
      if (data == null) {
        data = new Map<String, dynamic>();
      }
      data["token"] = token;
    }

    if (debug) {
      print('<net url>------$uri');
      print('<net params>------$data'); } // use json if it is a request body, otherwise it is a form (concatenated on the URL).if (dataIsJson) {
      op = new Options(contentType: ContentType.parse("application/json"));
    } else {
      op = new Options(
          contentType: ContentType.parse("application/x-www-form-urlencoded")); } op.method = method; /// Carry the tokenreturn _dio.request<Map<String, dynamic>>(
        method == "get" ? uri : "$uri? token=$enToken", data: data, options: op); } // if the request is successful, we will return the data we need, otherwise into the exception processing method, Static Future<T> logicalErrorTransform<T>(Response<Map<String, dynamic>> resp) {static Future<T> logicalErrorTransform<T>(Response<Map<String, dynamic>> resp) {if(resp.data ! = null) {if (resp.data["code"] == 0) {
        T realData = resp.data["data"];
        returnFuture.value(realData); }}if (debug) {
      print('resp--------$resp');
      print('resp.data--------${resp.data}');
    }

    LogicError error;
    if(resp.data ! = null && resp.data["code"] != 0) {
      if (resp.data['data']! Map<String, dynamic> realData = resp.data["data"];
        error = new LogicError(resp.data["code"], realData['codeMessage']);
      } else{/// error = new LogicError(resp.data["code"], resp.data["message"]); }}else {
      error = unknowError;
    }
    returnFuture.error(error); } static getToken() async {String token = await localstorage.get (localstorage.token_key);returntoken; }} class LogicError {int errorCode; String msg; LogicError(errorCode, msg) { this.errorCode = errorCode; this.msg = msg; }}Copy the code

Completes the basic package above, basic covers all methods, in addition to download, let’s take a look at a unified login exception handling, when listening to a long-distance login login or other abnormal, we need to let the user know, sometimes I need to go directly to the login page, here goes to routing jump, We need the context, and to get the context, we can write a listener class to use with the interface

class LoginInvalidHandler {
  BuildContext currentContext;
  LoginInvalidHandler(this.currentContext);

  Future<Null> loginInvalidHandler(dynamic errorMsg) {
    if(errorMsg ! = null && errorMsg is LogicError && errorMsg.errorCode == 10000) { LocalStorage.clearLoginInfo(); Fluttertoast.showToast( msg:'Your login has expired, please log in again', gravity: ToastGravity.CENTER, timeInSecForIos: 3); / / / into the login page of routing jump. / / NavigatorUtils goPwdLogin (currentContext);return Future.error(errorMsg);
    }
    return Future.error(errorMsg);
  }
}


Future<Null> nullFutureHandler(dynamic data){
  return Future.value(null);
}
Copy the code

With that in mind, everything is ready to go. The next step is the interface. We can write an Api class.

Class ApiInterface {/// Obtain the VERIFICATION code static final String _API_GET_SMS =""; static Future<Map<String, dynamic>> getSmsCode( String flag, String phoneNum, String vefifyCode) async {/// call the encapsulated NetUtilreturn NetUtil.postJson(_API_GET_SMS,
        {"flagId": flag, "phone": phoneNum, "vefifyCode": vefifyCode}); } // LoginInvalidHandler checks the LoginInvalidHandler exception on the interface requiring login verification. // LoginInvalidHandler Checks that the handler automatically enters the login page with the token expiration. // putForm is used here. Static final String _API_SET_PPWD ="user";
  static Future<Map<String, dynamic>> tradepassword(LoginInvalidHandler handler,
      String tradePassword, String checkTradePassword) async {
    return NetUtil.putForm(_API_SET_PPWD, {
      'tradePassword': tradePassword,
      'checkTradePassword': checkTradePassword
    }).catchError(handler.loginInvalidHandler);
  }
Copy the code

The last thing is to make the call

/ / / call ApiInterface. Tradepassword (LoginInvalidHandler (context), 'SSS','kjkkl').then((data) {catchError((errorMsg) {/// failed to enter a custom error interceptionif (errorMsg is LogicError) {
    LogicError logicError = errorMsg;
  
  } else{/// request failed dio exception}});Copy the code

After the above encapsulation, we use it very smoothly, write code that is flying keyboard!

Attach the Github portal

Like the little partners to the article little praise oh! Github dot star what! Ha ha!

Welcome everyone to pay attention to the public account: the interviewer said that here will share the interview process in all aspects, including resume optimization, interview preparation, all kinds of interviews, experience sharing, and so on interesting things.