Flutter网络请求库Dio的封装(单例、动态baseUrl、拦截器)

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

 

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


 
image.png

HttpManager的定义

构造全局单例,配置请求参数,配置通用的GET\POST,支持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, 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
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

你可能感兴趣的:(Flutter网络请求库Dio的封装(单例、动态baseUrl、拦截器))