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
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
原文地址:https://www.cnblogs.com/sundaysme/p/12624185.html