Flutter 网络请求框架封装详解

发布时间:2019-08-08 发布网站:脚本宝典
脚本宝典收集整理的这篇文章主要介绍了Flutter 网络请求框架封装详解脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。

 Flutter 请求网络的三种方式

flutter 请求网络的方式有三种,分别是 Dart 原生的网络请求 HttpClient、第三方网络请求 http以及 Flutter 中的 Dio。我们可以比较一下这三种网络请求方式,然后封装为我们方便请求网络的工具类。

Dart 原生的网络请求 HttpClient

实现 Dart 获取网络数据的请求,一般我们需要以下几个步骤:

step 1: 原生的网络请求时不需要修改 pubsPEc.yaml 文件的,我们只需要在使用的地方引入所需包就可以了

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

step 2:创建一个HttpClient

 HttpClient httpClient = new HttpClient();

step 3: 打开HttP连接,设置请求头

 HttpClientRequest request = await httpClient.getUrl(uri);

在这一步中,我们可以设置人意的的请求方法,比如 Get 请求、Post 请求、Delete 请求。

例如:携带参数的请求

 Uri uri=Uri(scheme: "https", host: "flutterchina.club", queryParameters: {   "userName":"chen",   "password":"123456"  });

例如:设置请求的 header

 request.headers.add("user-agent", "test"); request.headers.add("Authorization", "LKSJDLFJSDLKJSLKklsdj");

step 4: 等待连接服务器

 HttpClientResponse response = awaIT request.close();

step 5: 读取响应内容

 if (response.statusCode == HttpStatus.ok) {    _content = await response.transform(Utf8Decoder()).join(); }

step 6: 断开连接

 httpClient.close();

以上的步骤是 dart 简单获取网络的方式,我们从上面可以看到,通过 HttpClient 发起网络请求时比较麻烦的,很多都要我们亲手处理,还有 Cookie 的管理也是比较麻烦的。

库 http step

1:pubspec.yaML 添加依赖

 http: '>=0.11.3+12'

step 2: 在使用的地方导包

 import 'package:http/http.dart' as http;

step 3: 发起请求

Get 请求

 void getRequest() async {   VAR client = http.Client();   http.Response response = await client.get(url_2);   _content = response.body;  }

Post 请求

  void postRequest() async {   var params = Map<String, String>();   params["username"] = "hellonews";   params["password"] = "123456";    var client = http.Client();   var response = await client.post(url_post, body: params);   _content = response.body;  }

相对比 Dart 原生的网络请求,第三方库 http 的网络请求方式是要方便好多,写起来也是挺爽的。

Flutter 发布的 dio

Dio 一个强大的 Dart Http 请求库,支持 Restful API、FormData、拦截器、请求取消、Cookie管理、文件上传/下载、超时等...

step 1:pubspec.yaml 添加依赖

 dependencies:  dio: ^1.0.9

step 2:导入引用包

 import 'package:dio/dio.dart';

step 3:发起网络请求

Get 请求

 void getRequest() async {   Dio dio = new Dio();   var response = await dio.get("/test&#63;id=12&name=chen");   _content = response.data.toString();  }

对于 query 参数,我们可以通过对象来进行传递,上面的代码等同于:

 void getRequest() async {   Dio dio = new Dio();   var response = await dio.get("/test",data:{"id":12,"name":"chen"});   _content = response.data.toString();  }

Post 请求

  void postRequest() async {   var dio = new Dio();   var response = await dio.post(url_post, data:{"id":12,"name":"wendu"});   _content = response.data.toString();  }

Dio 网络请求框架封装

 日志信息拦截

Dio 和 okhttp 一样,都会有一个请求拦截器和响应拦截器,通过拦截器,我们可以在请求之前或响应之后做一些同意的预处理。例如我们发起请求前查看我们请求的参数和头部,响应的时候,我们可以查看返回来的数据。

   Dio dio = new Dio();   // 添加拦截器   if (config.DEBUG) {    dio.interceptors.add(InterceptorsWrapper(      onRequest: (RequestOptions options){       PRint("/n================== 请求数据 ==========================");       print("url = ${options.uri.toString()}");       print("headers = ${options.headers}");       print("params = ${options.data}");      },      onResponse: (Response response){       print("/n================== 响应数据 ==========================");       print("code = ${response.statusCode}");       print("data = ${response.data}");       print("/n");      },      onError: (DioError e){       print("/n================== 错误响应数据 ======================");       print("type = ${e.type}");       print("message = ${e.message}");       print("stackTrace = ${e.stackTrace}");       print("/n");      }    ));   }

如果我们想要移除拦截器,那么我们可以将其设置为 null

 dio.interceptor.request.onSend=null; dio.interceptor.response.onSuccess=null; dio.interceptor.response.onError=null;

token 添加

   // 头部添加 token 验证   headers["Authorization"] = "token lskjdlklsjkdklsjd333";   option.headers = headers;   ///超时   option.connectTimeout = 15000;   try {    Response response = await dio.request(url, data: params, options: option);   } on DioError catch (e) {    // 请求错误处理   }

自动生成 dart 的 JSON 实体类插件 FlutterJsonBeanFactory

在 AndROId 开发中,有 GsonFormat 这个插件来讲 json 数据自动转化成 Bean;那么在 Flutter 中也有类似的插件可以生产序列化的实体类的插件:FlutterJsonBeanFactory

step 1:下载插件 FlutterJsonBeanFactory,安装完成后重启

Setting -> Plugins -> browse Respositories 中搜索 FlutterJsonBeanFactory

step 2:创建实体类,在指定目录下:

New -> dart bean class File From JSON

Flutter 网络请求框架封装详解

step 3:输入实体类名及 json 格式的数据

Flutter 网络请求框架封装详解

step 4:最后生成的实体类:LOGinEntity

 class LoginEntity {  String eaSEMobpassword;  String username;   LoginEntity({this.easemobpassword, this.username});   LoginEntity.fromJson(Map<String, dynamic> json) {   easemobpassword = json['easemobPassword'];   username = json['username'];  }   Map<String, dynamic> toJson() {   final Map<String, dynamic> data = new Map<String, dynamic>();   data['easemobPassword'] = this.easemobpassword;   data['username'] = this.username;   return data;  } }

请求错误处理

  Response response;   try {    response = await dio.request(url, data: params, options: option);   } on DioError catch (e) {    // 请求错误处理    Response errorResponse;    if (e.response != null) {     errorResponse = e.response;    } else {     errorResponse = new Response(statusCode: 666);    }    if (e.type == DioErrorType.CONNECT_TIMEOUT) {     errorResponse.statusCode = Code.NETWORK_TIMEOUT;    }    if (Config.DEBUG) {     print('请求异常: ' + e.toString());     print('请求异常 url: ' + url);    }    return new ResultData(Code.errorHandleFunction(errorResponse.statusCode, e.message, noTip), false, errorResponse.statusCode);   }

其中 ResultData 是网络结果处理的实体类

 /**  * 网络结果数据  * Created by chenjianrun  * Date: 2018-07-16  */ class ResultData {  var data;  bool result;  int code;  var headers;   ResultData(this.data, this.result, this.code, {this.headers}); }

Code 是处理网络错误的编码,并将错误结果通过 eventbus 发送出去,一般我们可以在 main_pager 中注册监听这个事件。

 ///网络请求错误编码 class Code {  ///网络错误  static const NETWORK_ERROR = -1;   ///网络超时  static const NETWORK_TIMEOUT = -2;   ///网络返回数据格式化一次  static const NETWORK_JSON_EXCEPTION = -3;   static const SUCCESS = 200;   static final EventBus eventBus = new EventBus();   static errorHandleFunction(code, message, noTip) {   if(noTip) {    return message;   }   eventBus.fire(new HttpErrorevent(code, message));   return message;  } }

完成的网络请求类:HttpRequest

 import 'dart:io';  import 'package:dio/dio.dart'; import 'package:private_tutor/common/SpUtils.dart'; import 'package:connectivity/connectivity.dart';  import 'dart:collection';  import 'package:private_tutor/common/config/Config.dart'; import 'package:private_tutor/net/ResultCode.dart'; import 'package:private_tutor/net/ResultData.dart';  ///http请求管理类,可单独抽取出来 class HttpRequest {  static String _baseUrl;  static const CONTENT_TYPE_JSON = "application/json";  static const CONTENT_TYPE_FORM = "application/x-www-form-urlencoded";  static Map optionParams = {   "timeoutMs": 15000,   "token": null,   "authorizationCode": null,  };   static setBaseUrl(String baseUrl){   _baseUrl = baseUrl;  }   static get(url,param) async{   return await request(_baseUrl+url, param, null, new Options(method:"GET"));  }   static post(url,param) async{   return await request(_baseUrl+url, param, {"Accept": 'application/vnd.github.VERSION.full+json'}, new Options(method: 'POST'));  }   static delete(url,param) async{   return await request(_baseUrl+url, param, null, new Options(method: 'DELETE'));  }   static put(url,param) async{   return await request(_baseUrl+url, param, null, new Options(method: "PUT", contentType: ContentType.text));  }   ///发起网络请求  ///[ url] 请求url  ///[ params] 请求参数  ///[ header] 外加头  ///[ option] 配置  static request(url, params, Map<String, String> header, Options option, {noTip = false}) async {    //没有网络   var connectivityResult = await (new Connectivity().checkConnectivity());   if (connectivityResult == ConnectivityResult.none) {    return new ResultData(Code.errorHandleFunction(Code.NETWORK_ERROR, "", noTip), false, Code.NETWORK_ERROR);   }    Map<String, String> headers = new HashMap();   if (header != null) {    headers.addAll(header);   }    //授权码   if (optionParams["authorizationCode"] == null) {    var authorizationCode = await getAuthorization();    if (authorizationCode != null) {     optionParams["authorizationCode"] = authorizationCode;    }   }    headers["Authorization"] = optionParams["authorizationCode"];   // 设置 baseUrl      if (option != null) {    option.headers = headers;   } else{    option = new Options(method: "get");    option.headers = headers;   }    ///超时   option.connectTimeout = 15000;    Dio dio = new Dio();   // 添加拦截器   if (Config.DEBUG) {    dio.interceptors.add(InterceptorsWrapper(      onRequest: (RequestOptions options){       print("/n================== 请求数据 ==========================");       print("url = ${options.uri.toString()}");       print("headers = ${options.headers}");       print("params = ${options.data}");      },      onResponse: (Response response){       print("/n================== 响应数据 ==========================");       print("code = ${response.statusCode}");       print("data = ${response.data}");       print("/n");      },      onError: (DioError e){       print("/n================== 错误响应数据 ======================");       print("type = ${e.type}");       print("message = ${e.message}");       print("stackTrace = ${e.stackTrace}");       print("/n");      }    ));   }    Response response;   try {    response = await dio.request(url, data: params, options: option);   } on DioError catch (e) {    // 请求错误处理    Response errorResponse;    if (e.response != null) {     errorResponse = e.response;    } else {     errorResponse = new Response(statusCode: 666);    }    if (e.type == DioErrorType.CONNECT_TIMEOUT) {     errorResponse.statusCode = Code.NETWORK_TIMEOUT;    }    if (Config.DEBUG) {     print('请求异常: ' + e.toString());     print('请求异常 url: ' + url);    }    return new ResultData(Code.errorHandleFunction(errorResponse.statusCode, e.message, noTip), false, errorResponse.statusCode);   }    try {    if (option.contentType != null && option.contentType.PrimaryType == "text") {     return new ResultData(response.data, true, Code.SUCCESS);    } else {     var responseJson = response.data;     if (response.statusCode == 201 && responseJson["token"] != null) {      optionParams["authorizationCode"] = 'token ' + responseJson["token"];      await SpUtils.save(Config.TOKEN_KEY, optionParams["authorizationCode"]);     }    }    if (response.statusCode == 200 || response.statusCode == 201) {     return ResultData(response.data, true, Code.SUCCESS, headers: response.headers);    }   } catch (e) {    print(e.toString() + url);    return ResultData(response.data, false, response.statusCode, headers: response.headers);   }   return new ResultData(Code.errorHandleFunction(response.statusCode, "", noTip), false, response.statusCode);  }   ///清除授权  static clearAuthorization() {   optionParams["authorizationCode"] = null;   SpUtils.remove(Config.TOKEN_KEY);  }   ///获取授权token  static getAuthorization() async {   String token = await SpUtils.get(Config.TOKEN_KEY);   if (token == null) {    String basic = await SpUtils.get(Config.USER_BASIC_CODE);    if (basic == null) {     //提示输入账号密码    } else {     //通过 basic 去获取token,获取到设置,返回token     return "Basic $basic";    }   } else {    optionParams["authorizationCode"] = token;    return token;   }  } }

使用示例

 /// 登录 model class LoginModel{   // 手机号码登录  static phoneLogin(String phone,String verifyCode) async{   ResultData response = await HttpRequest.post(Address.phoneLogin, {"phoneNum" : phone,"captcha":verifyCode});   if(response != null && response.result){     PhoneLoginEntity phoneLoginEntity = PhoneLoginEntity.fromJson(json.decode(response.data));     return new DataResult(phoneLoginEntity, true);   }else{    return new DataResult(null, false);   }  }    // 获取验证码  static getVerifyCode(String phone) async{   ResultData response = await HttpRequest.get("${Address.getVerifyCode}?phone=${phone}", null);  //  var response = await HttpRequest.get(Address.getVerifyCode, {"phone":phone});   if(response != null && response.result){    VerifyCodeEntity entity = VerifyCodeEntity.fromJson(response.data);    return new DataResult(entity, true);   }else{    return new DataResult(null, false);   }  } }
android教程
脚本网站
android studio

脚本宝典总结

以上是脚本宝典为你收集整理的Flutter 网络请求框架封装详解全部内容,希望文章能够帮你解决Flutter 网络请求框架封装详解所遇到的问题。

如果觉得脚本宝典网站内容还不错,欢迎将脚本宝典推荐好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。