zoukankan      html  css  js  c++  java
  • Flutter网络请求库Dio的封装(单例、动态baseUrl、拦截器)

    https://www.jianshu.com/p/5ead0cf96642

    封装网络请求的几个好处:
    1、便于统一配置请求参数,如header,公共参数,加密规则等
    2、方便调试,日志打印
    3、优化代码性能,避免到处滥new对象,构建全局单例
    4、简化请求步骤,只暴露需要的响应数据,而对错误的响应统一回调
    5、对接口数据的基类封装,简化解析流程
    效果示例:


     
    image.png

    HttpManager的定义

    构造全局单例,配置请求参数,配置通用的GETPOST,支持baseUrl的切换

    class HttpManager {
      static HttpManager _instance = HttpManager._internal();
      Dio _dio;
    
      factory HttpManager() => _instance;
    
      ///通用全局单例,第一次使用时初始化
      HttpManager._internal({String baseUrl}) {
        if (null == _dio) {
          _dio = new Dio(new BaseOptions(
              baseUrl: Address.BASE_URL_RELEASE, connectTimeout: 15000));
          _dio.interceptors.add(new LogsInterceptors());
          _dio.interceptors.add(new ResponseInterceptors());
        }
      }
    
      static HttpManager getInstance({String baseUrl}) {
        if (baseUrl == null) {
          return _instance._normal();
        } else {
          return _instance._baseUrl(baseUrl);
        }
      }
    
      //用于指定特定域名,比如cdn和kline首次的http请求
      HttpManager _baseUrl(String baseUrl) {
        if (_dio != null) {
          _dio.options.baseUrl = baseUrl;
        }
        return this;
      }
    
      //一般请求,默认域名
      HttpManager _normal() {
        if (_dio != null) {
          if (_dio.options.baseUrl != Address.BASE_URL_RELEASE) {
            _dio.options.baseUrl = Address.BASE_URL_RELEASE;
          }
        }
        return this;
      }
    
      ///通用的GET请求
      get(url, params, {noTip = false}) async {
        Response response;
        try {
          response = await _dio.get(url, queryParameters: params);
        } on DioError catch (e) {
          return resultError(e);
        }
    
        if (response.data is DioError) {
          return resultError(response.data['code']);
        }
    
        return response.data;
      }
    ///通用的POST请求
      post(url, params, {noTip = false}) async {
        Response response;
    
        try {
          response = await _dio.post(url, data: params);
        } on DioError catch (e) {
          return resultError(e);
        }
    
        if (response.data is DioError) {
          return resultError(response.data['code']);
        }
    
        return response.data;
      }
    }
    

    日志拦截器

    打印请求参数和返回参数

    import 'package:dio/dio.dart';
    
    class LogsInterceptors extends InterceptorsWrapper {
      

    响应拦截器

    过滤正确的响应数据,对数据进行初步封装

    import 'package:dio/dio.dart';
    import 'package:exchange_flutter/common/net/code.dart';
    import 'package:flutter/material.dart';
    import '../result_data.dart';
    
    class ResponseInterceptors extends InterceptorsWrapper {
      @override
      onResponse(Response response) {
        RequestOptions option = response.request;
        try {
          if (option.contentType != null &&
              option.contentType.primaryType == "text") {
            return new ResultData(response.data, true, Code.SUCCESS);
          }
          ///一般只需要处理200的情况,300、400、500保留错误信息
          if (response.statusCode == 200 || response.statusCode == 201) {
            int code = response.data["code"];
            if (code == 0) {
              return new ResultData(response.data, true, Code.SUCCESS,
                  headers: response.headers);
            } else if (code == 100006 || code == 100007) {
    
            } else {
              Fluttertoast.showToast(msg: response.data["msg"]);
              return new ResultData(response.data, false, Code.SUCCESS,
                  headers: response.headers);
            }
          }
        } catch (e) {
          print(e.toString() + option.path);
    
          return new ResultData(response.data, false, response.statusCode,
              headers: response.headers);
        }
    
        return new ResultData(response.data, false, response.statusCode,
            headers: response.headers);
      }
    }
    
    

    响应基类

    默认200的情况isSuccess为true,响应为response.data,赋值给data

    class ResultData {
      var data;
      bool isSuccess;
      int code;
      var headers;
    
      ResultData(this.data, this.isSuccess, this.code, {this.headers});
    }
    

    Api的封装

    请求的集中管理

    class Api {
      ///示例请求
      static request(String param) {
        var params = DataHelper.getBaseMap();
        params['param'] = param;
        return HttpManager.getInstance().get(Address.TEST_API, params);
      }
    }
    

    公共参数和加密等

    class DataHelper{
      static SplayTreeMap getBaseMap() {
        var map = new SplayTreeMap<String, dynamic>();
        map["platform"] = AppConstants.PLATFORM;
        map["system"] = AppConstants.SYSTEM;
        map["channel"] = AppConstants.CHANNEL;
        map["time"] = new DateTime.now().millisecondsSinceEpoch.toString();
        return map;
      }
      
      static string2MD5(String data) {
        var content = new Utf8Encoder().convert(data);
        var digest = md5.convert(content);
        return hex.encode(digest.bytes);
      }
    }
    

    地址的配置

    方便地址管理

    class Address {
      static const String TEST_API =  "test_api";
    }
    

    示例请求

    dart的json解析推荐使用json_serializable,其他的有些坑,慎用

    void request() async {
        ResultData res = await Api.request("param");
        if (res.isSuccess) {
           //拿到res.data就可以进行Json解析了,这里一般用来构造实体类
                TestBean bean = TestBean.fromMap(res.data);
    
        }else{
          //处理错误
        }
      }
    

    Demo地址 https://github.com/po1arbear/Flutter-Net.git



    作者:刺客的幻影
    链接:https://www.jianshu.com/p/5ead0cf96642
    来源:简书
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
  • 相关阅读:
    负载(Load)分析及问题排查
    MySQL 数据库规范--调优篇(终结篇)
    AbstractQueuedSynchronizer
    为什么String被设计为不可变?是否真的不可变?
    数据库 分库 分表 分区
    Oracle 数据库知识汇总篇
    小知识:如何判断数据文件的高水位线
    RHEL7安装11204 RAC的注意事项
    案例:DG主库未设置force logging导致备库坏块
    Oracle 11g RAC之HAIP相关问题总结
  • 原文地址:https://www.cnblogs.com/sundaysme/p/12624185.html
Copyright © 2011-2022 走看看