美文网首页
Flutter网络请求库Dio与Future特性

Flutter网络请求库Dio与Future特性

作者: 许久以前 | 来源:发表于2019-06-25 14:59 被阅读0次

    Flutter自带的网络请求引擎HttpClient功能,但HttpClient本身功能较弱,很多常用功能都不支持。Dio是Flutter的一个第三方网络库,它是一个强大易用的dart http请求库,支持Restful API、FormData、拦截器、请求取消、Cookie管理、文件上传/下载、超时等。

    Dio使用方法

    1.添加依赖:

    dependencies:
      dio: ^x.x.x  // 请使用pub上的最新版本
    

    2.在调用的文件导入:

    import 'package:dio/dio.dart';
    

    3.发起一个Post网络请求:

    Response response = await dio.post(
              url , 
              data: paramters,
              options: opt,
            );
    

    url 表示请求的地址;
    data:Post提交的参数,key-value的Map类型;
    options参数:网络请求头设置、其他自定义配置等。

    其中Options是一个配置类:

    Options({
        String method,
        int connectTimeout,
        int sendTimeout,
        int receiveTimeout,
        Iterable<Cookie> cookies,
        Map<String, dynamic> extra,
        Map<String, dynamic> headers,
        ResponseType responseType,
        ContentType contentType,
        ValidateStatus validateStatus,
        bool receiveDataWhenStatusError,
        bool followRedirects,
        int maxRedirects,
      })
    

    通过其内部的属性可以看到,可以设置
    method:Get/Post方式;
    connectTimeout超时时间(毫秒单位);
    headers就是设置请求头。
    contentType和responseType可设置返回的内容是xml/json/text-plain等格式。
    followRedirects可设置是否允许重定向。
    cookies可以设置cookies。

    Dart Future

    网络请求离不开异步机制,Dart语法特性对异步机制使用了Future机制。这套机制和ES6的Promise原理是一样的。

    如果你对Js的ES6熟悉,那么你将很容易理解和使用。他们都是协程,大致都是采用async/await 机制,将一个异步请求的过程放入一个协程里面,将结果以“同步”的方式返回,注意:不是真正的同步请求,实际上任何异步请求都是天然存在的客观事实,你无法真正将一个异步请求改成一个同步请求。

    回到我们Dart语法中:
    像上面的post请求方法,如果一个方法是异步的,那么该方法在没有返回结果前需要等待,dart语法要求在方法前加上“await”标识:

    await xxxxxx()

    那么,响应的该语句执行的方法返回也必须在结尾添加异步标识async:

    Future xxxxxxx(paramters) async {
    await xxxxxx()
    }

    该方法的放回类型一般为Future类型,以便调用方使用then()取得结果。(注意:返回类型不必一定为Future,可也是void,那么调用方就不能使用then()取结果而已)。

    可能很多人不知道Future标识有什么意思,标识Future标识该方法的返回是一个then()-catchError(e)结果体,其中then({闭包})里是正确的返回结果,catchError({闭包})就是异步异常的结果。

    当然,异步的请求也可以不以Future形式返回,我们可以通过自定义闭包结构体返回,比如我的网络请求返回是2个callback:

    void request (String url, 
                    Map paramters, 
                    Function completeCallback, 
                    Function errorCallback) async {
    
        if (!url.startsWith("http")) {
          String baseUrl = "https://www.wowoshenghuo.com";
          url = baseUrl + url;
        }
        String errorMsg = "";
        try {
          Options opt = await wowoLifeHeaders();
          Response response = await dio.post(
              url , 
              data: paramters,
              options: opt,
            );
          print("网络请求状态码:" + response.statusCode.toString());
          //处理错误部分
          if (response.statusCode < 200 || response.statusCode > 400) {
            errorMsg = "网络请求错误,状态码:" + response.statusCode.toString();
            _handError(errorCallback, errorMsg);
            return;
          }
    
          //网络connected
          Map<String, dynamic> json;
          if (response.data is Map) {
            json = response.data;
          }else {
            json = jsonDecode(response.data);
          }
          print(json);
          //转模型
          YWResponse resp = YWResponse.fromJson(json);
          
          if (completeCallback != null) {
            completeCallback(resp);
          }
    
        } catch(exception) {
          _handError(errorCallback, exception.toString());
        }
      }
    
      void _handError(Function errorCallback, String errorMsg) {
        if (errorCallback != null) {
          errorCallback(errorMsg);
        }
      }
    
    }
    

    我的网络返回是通过两个Function返回的:
    completeCallback:网络正常的回调(当然业务错误也属于这种)
    errorCallback:网络异常、不通的回调。

    虽然我的网络请求是async标识的,由于我自定义了网络回调,所以我仅仅申明void返回即可。

    获取设备信息和APP包信息

    我们经常需要获取手机设备诸如系统版本,平台信息以及APP包名称,APP版本等信息。这些Flutter有一些第三方插件提供了这方面的api.

    device_info

    device_info 插件同样需要安装然后import
    初始化:

    DeviceInfoPlugin deviceInfo = DeviceInfoPlugin();

    deviceInfo为我们提供了iosInfo和androidInfo;
    那么我们首先需要自己判断当前设备是哪个平台:

    if (Platform.isIOS) {
          IosDeviceInfo iosInfo = await deviceInfo.iosInfo;
          device["sysVersion"] = iosInfo.systemVersion;
          device["model"] = iosInfo.localizedModel;
          device["imei"] = iosInfo.identifierForVendor;
          device["brand"] = "iPhone";
        }else {
          AndroidDeviceInfo androidInfo = await deviceInfo.androidInfo;
          device["sysVersion"] = androidInfo.version.baseOS;
          device["model"] = androidInfo.model;
          device["imei"] = androidInfo.id;
          device["brand"] = androidInfo.brand;
        }
    

    然后通过iosInfo或者AndroidInfo即可获取system、model等设备信息。
    需要注意的是:deviceInfo获取设备信息的方法是个异步的
    需要await/async。

    package_info

    package_info是读取APP工程的信息的,如APP名称、APP唯一标识、APP迭代版本号等。
    同样,和device_info一样,这个方法也是异步获取pakage信息:

    Future<PackageInfo> pakageInfo() async {
        PackageInfo packageInfo = await PackageInfo.fromPlatform();
        return packageInfo;
      }
    

    最后根据我们公司需要将设备信息作为header的获取方法全部完成了,贴一下我的header代码:

    Future<Options> wowoLifeHeaders() async {
    
        if (store == null) {
          store = await storage();
        }
        if (deviceMap == null) {
          deviceMap = await deviceSystemVersion();
        }
        if (pakage == null) {
          pakage = await pakageInfo();
        }
    
        String uToken = "-1";
        if (store != null && store.getString("user_token") != null) {
          uToken = store.getString("user_token");
        } 
        Options options = Options(
          headers: {
            HttpHeaders.contentTypeHeader:"application/json;charset=UTF-8",
            "source" : Platform.isIOS ? "2" : "1",
            "sys_version" : deviceMap["sysVersion"],
            "model" : deviceMap["model"],
            "imei" : deviceMap["imei"],
            "app_version" : pakage.version,
            "user_token" : uToken,
            "userToken" : uToken,
          },
          connectTimeout: 30000,
          receiveTimeout: 25000,
          contentType: ContentType.json,
          responseType: ResponseType.json,
          );
        return options;
      }
    

    以上。

    相关文章

      网友评论

          本文标题:Flutter网络请求库Dio与Future特性

          本文链接:https://www.haomeiwen.com/subject/kkxtcctx.html