Flutter用dio封装http网络请求,设置统一的请求地址、headers及处理返回内容
封装http请求是项目中经常需要做的,常用于设置通用请求地址、请求headers以及处理返回结果,例如在项目中开发地址、测试地址、上线地址是不一样的,当在封装的请求设置好默认地址之后只需要改一个地址而不需要每一个接口都去修改,以及统一在headers设置token用来校验身份等。
先来看一下完成后的使用方法把(格式是不是有点像ajax)
HttpUtil.get(
url,
data: {
key: value
},
headers: {
key: value
}
success: (data){
// 请求成功返回的数据
},error: (errorMsg){
// 请求失败返回的错误信息
}
);
封装实现
使用dio先在pubspec.yaml添加dio包,然后packages get,获取最新的版本https://pub.dev/packages/dio
dio: ^2.1.7
然后在封装的地方引用它
import 'package:dio/dio.dart';
在页面中先设置一个请求地址
class BaseUrl{
  // 配置默认请求地址
  static const String url = 'http://127.0.0.1';
}
再建立一个HttpUtil类,把请求方法写在里面,先来实现一下get请求,在方法中写好可接收的参数,url必填其他选填
class HttpUtil{
  static void get(
    String url,
    {
      Map<String, dynamic> data,
      Map<String, dynamic> headers,
      Function success,
      Function error
    }
  ) async {
    // 对接收到的请求参数进行从处理
  }
}
在get请求中携带参数的用字符串拼接的形式例如:http://127.0.0.1/vod/getPlayInfo?userid=bd2439487ce6540a68ce01b8f57242eb6&number=5,所以在接收到请求携带的参数后如果请求参数不为空需要对携带的参数其进行拼接处理
// 数据拼接
if(data != null && data.isNotEmpty){
StringBuffer options= new StringBuffer('?');
data.forEach((key, value){
options.write('${key}=${value}&');
});
String optionsStr = options.toString();
optionsStr = optionsStr.substring(0, optionsStr.length - 1);
url += optionsStr;
}
数据拼接完成之后即可发起请求,把请求写到一个_sendRequest方法中,然后进行进一步的处理
// 发送get请求
await _sendRequest(
url,
'get',
success,
headers: headers,
error: error
);
在写_sendRequest方法之前先看后端返回格式,我这边的返回格式是这样的,当请求成功后端code返回0,失败会返回其他失败码及提示信息
{
  "code": 0,                         // int
  "msg": "后端返回失败提示信息",        // string
  "data": {}                        // 这可能是对象,也可能数数组
}
下面来实现_sendRequest方法,当获取到请求的url后进行判断,如果url是以http开头的就可认为其是完整地址,那就直接使用传过来的地址,如果不是以http开头的,那就使用设置的默认地址来拼接请求地址
// 请求处理
static Future _sendRequest(
String url,
String method,
Function success,
{
Map<String, dynamic> data,
Map<String, dynamic> headers,
Function error
}
) async {
int _code;
String _msg;
var _backData; // 检测请求地址是否是完整地址
if(!url.startsWith('http')){
url = BaseUrl.url + url;
} }
发起请求
在请求之前先判断data和headers是否为空,然后配置dio的请求信息,查看dio更多API:https://github.com/flutterchina/dio
try{
  Map<String, dynamic> dataMap = data == null ? new Map() : data;
  Map<String, dynamic> headersMap = headers == null ? new Map() : headers;
  // 配置dio请求信息
  Response response;
  Dio dio = new Dio();
  dio.options.connectTimeout = 10000;        // 服务器链接超时,毫秒
  dio.options.receiveTimeout = 3000;         // 响应流上前后两次接受到数据的间隔,毫秒
  dio.options.headers.addAll(headersMap);    // 添加headers,如需设置统一的headers信息也可在此添加
  if(method == 'get'){
    response = await dio.get(url);
  }else{
    response = await dio.post(url,data: dataMap);
  }
}catch(exception){
  _handError(error, '数据请求错误:'+exception.toString());
}
请求结果处理
先判断请求状态是否为200,否则返回请求错误;然后看后端返回的code是否为0,不为0则返回状态吗+错误信息
if(response.statusCode != 200){
  _msg = '网络请求错误,状态码:' + response.statusCode.toString();
  _handError(error, _msg);
  return;
}
// 返回结果处理
Map<String, dynamic> resCallbackMap = response.data;
_code = resCallbackMap['code'];
_msg = resCallbackMap['msg'];
_backData = resCallbackMap['data'];
if(success != null){
  if(_code == 0){
    success(_backData);
  }else{
    String errorMsg = _code.toString()+':'+_msg;
    _handError(error, errorMsg);
  }
}
最后再写一个返回错误信息的方法
// 返回错误信息
static Future _handError(Function errorCallback,String errorMsg){
if(errorCallback != null){
errorCallback(errorMsg);
}
}
完成后测试一下一个get请求,测试的json如下
{
	"code": 0,
	"msg": "",
	"data": {
		"backResult": "返回成功啦"
	}
}
请求代码
HttpUtil.get(
'/app_model/httptest.json',
success: (data){
print(data.toString());
},error: (errorMsg){
print(errorMsg);
}
);
返回结果如下:
I/flutter ( 7871): {backResult: 返回成功啦}
完整代码
源文件可以到git获取https://gitee.com/daydayfull/flutter_httputil
import 'package:dio/dio.dart';
class BaseUrl{
  // 配置默认请求地址
  static const String url = 'http://127.0.0.1';
}
class HttpUtil{
  static void get(
    String url,
    {
      Map<String, dynamic> data,
      Map<String, dynamic> headers,
      Function success,
      Function error
    }
  ) async {
    // 数据拼接
    if(data != null && data.isNotEmpty){
      StringBuffer options= new StringBuffer('?');
      data.forEach((key, value){
        options.write('${key}=${value}&');
      });
      String optionsStr = options.toString();
      optionsStr = optionsStr.substring(0, optionsStr.length - 1);
      url += optionsStr;
    }
    // 发送get请求
    await _sendRequest(
        url,
        'get',
        success,
        headers: headers,
        error: error
    );
  }
  static void post(
    String url,
    {
      Map<String, dynamic> data,
      Map<String, dynamic> headers,
      Function success,
      Function error
    }
  ) async {
    // 发送post请求
    _sendRequest(
      url,
      'post',
      success,
      data: data,
      headers: headers,
      error: error
    );
  }
  // 请求处理
  static Future _sendRequest(
    String url,
    String method,
    Function success,
    {
      Map<String, dynamic> data,
      Map<String, dynamic> headers,
      Function error
    }
  ) async {
    int _code;
    String _msg;
    var _backData;
    // 检测请求地址是否是完整地址
    if(!url.startsWith('http')){
      url = BaseUrl.url + url;
    }
    try{
      Map<String, dynamic> dataMap = data == null ? new Map() : data;
      Map<String, dynamic> headersMap = headers == null ? new Map() : headers;
      // 配置dio请求信息
      Response response;
      Dio dio = new Dio();
      dio.options.connectTimeout = 10000;        // 服务器链接超时,毫秒
      dio.options.receiveTimeout = 3000;         // 响应流上前后两次接受到数据的间隔,毫秒
      dio.options.headers.addAll(headersMap);    // 添加headers,如需设置统一的headers信息也可在此添加
      if(method == 'get'){
        response = await dio.get(url);
      }else{
        response = await dio.post(url,data: dataMap);
      }
      if(response.statusCode != 200){
        _msg = '网络请求错误,状态码:' + response.statusCode.toString();
        _handError(error, _msg);
        return;
      }
      // 返回结果处理
      Map<String, dynamic> resCallbackMap = response.data;
      _code = resCallbackMap['code'];
      _msg = resCallbackMap['msg'];
      _backData = resCallbackMap['data'];
      if(success != null){
        if(_code == 0){
          success(_backData);
        }else{
          String errorMsg = _code.toString()+':'+_msg;
          _handError(error, errorMsg);
        }
      }
    }catch(exception){
      _handError(error, '数据请求错误:'+exception.toString());
    }
  }
  // 返回错误信息
  static Future _handError(Function errorCallback,String errorMsg){
    if(errorCallback != null){
      errorCallback(errorMsg);
    }
  }
}
这里只简单写了get和post两个方法,在dio中提供了如下方法
Future get(...) Future post(...) Future put(...) Future delete(...) Future head(...) Future put(...) Future path(...) Future download(...)
Flutter用dio封装http网络请求,设置统一的请求地址、headers及处理返回内容的更多相关文章
- Retrofit2.0+OkHttp设置统一的请求头(request headers)
		
有时候要求Retrofit2的接口中每个都要增加上headers,又不想做重复的事情,可以使用这种方法来为每个request请求都设置上相同的请求头header. 修改请求头request heade ...
 - Android okHttp网络请求之Get/Post请求
		
前言: 之前项目中一直使用的Xutils开源框架,从xutils 2.1.5版本使用到最近的xutils 3.0,使用起来也是蛮方便的,只不过最近想着完善一下app中使用的开源框架,由于Xutils里 ...
 - Vue--axios:vue中的ajax异步请求(发送和请求数据)、vue-resource异步请求和跨域
		
跨域原理: 一.使用axios发送get请求 1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 & ...
 - 基于AFNetworking封装的网络请求工具类【原创】
		
今天给大家共享一个我自己封装的网络请求类,希望能帮助到大家. 前提,导入AFNetworking框架, 关于修改AFN源码:通常序列化时做对text/plan等的支持时,可以一劳永逸的修改源代码,在a ...
 - iOS 自己封装的网络请求,json解析的类
		
基本上所有的APP都会涉及网络这块,不管是用AFNetWorking还是自己写的http请求,整个网络框架的搭建很重要. 楼主封装的网络请求类,包括自己写的http请求和AFNetWorking的请求 ...
 - Flutter实战视频-移动电商-05.Dio基础_引入和简单的Get请求
		
05.Dio基础_引入和简单的Get请求 博客地址: https://jspang.com/post/FlutterShop.html#toc-4c7 第三方的http请求库叫做Dio https:/ ...
 - Flutter之Dio引入和简单的Get/Post请求
		
先在pubspec.yaml中引入Dio包如图所示 认识Dio库:dio是一个dart的 http请求通用库,目前也是大陆使用最广泛的库,国人开发,完全开源. flutter的插件包管理:学了引入di ...
 - iOS-AFNetworking封装Get(自定义HTTP Header)和Post请求及文件下载
		
前面提到AFNetworking是一个很强大的网络三方库,首先你需要引入AFNetworking三方库:如封装的有误还请指出,谢谢! 1.Get请求 /**Get请求 url 服务器请求地址 succ ...
 - 教你如何封装异步网络连接NSURLConnection实现带有百分比的下载
		
教你如何封装异步网络连接NSURLConnection实现带有百分比的下载 注:本教程需要你对block有着较为深刻的理解,且对如何封装对象有着一些经验. 也许你已经用惯了AFNetworking2. ...
 
随机推荐
- K2 BPM_当BPM遇上RPA | 企业合规和风险管理从此更高效_全球领先的工作流引擎
			
强化企业合规与风险管理已成为全球企业发展的共识,尤其是对于药企.银行.地产这类对于合规性要求高的企业而言,识别预测潜在的管理风险和遵循不断升级的合规义务,是保证企业平稳运行的关键. 如何从流程层面降低 ...
 - inotify和rsync实现数据实时同步
			
数据的实时同步 实现实时同步 要利用监控服务(inotify),监控同步数据服务器目录中信息的变化 发现目录中数据产生变化,就利用rsync服务推送到备份服务器上 实现实时同步的方法 ino ...
 - 15.Vue组件中的data
			
1.组件中展示数据和响应事件: // 1. 组件可以有自己的 data 数据 // 2. 组件的 data 和 实例的 data 有点不一样,实例中的 data 可以为一个对象 // 3. 但是组件中 ...
 - less-important
			
!important关键字:会为所有混合带来的样式,添加!important 在css里面加上!important,是所有样式优先级最高的 在less里面什么场景会用important,在调试的时候 ...
 - MySQL 进阶4 SQL常见函数: 字符函数/数学函数/日期函数/流程控制函数(if/case)
			
# 进阶4 SQL常见函数 分类: 1/单行函数: 字符函数: concat(),length(),ifnull(__,default) ,instr(), trim(),upper(),lower( ...
 - Java abstract类的基本使用 和  [abstract类实现]打印1000以内的所有素数并输出时间
			
笔记: /** 关键字abstract ,实现抽象类,相当于给出类的大纲,子类只管继承,但抽象类不可被实例化! * 1.抽象方法只保留方法的功能,而具体的执行,交给继承抽象类的子类,由子类重写所有的抽 ...
 - Cairo
			
Cairo 英[ˈkaɪrəʊ] 美[ˈkaɪroʊ] n. 开罗(埃及首都); [例句]From Cairo came expressions of regret at the attac
 - [转载]Java进程物理内存远大于Xmx的问题分析
			
进程物理内存远大于Xmx的问题分析 问题描述 最近经常被问到一个问题,”为什么我们系统进程占用的物理内存(Res/Rss)会远远大于设置的Xmx值”,比如Xmx设置1.7G,但是top看到的Res的值 ...
 - intelij idea 常用插件下载
			
本文,给大家推荐几款我私藏已久的,自己经常使用的,可以提升代码效率的插件.IDEA插件简介常见的IDEA插件主要有如下几类:常用工具支持Java日常开发需要接触到很多常用的工具,为了便于使用,很多工具 ...
 - JS window对象详解
			
window 是客户端浏览器对象模型的基类,window 对象是客户端 JavaScript 的全局对象.一个 window 对象实际上就是一个独立的窗口,对于框架页面来说,浏览器窗口每个框架都包含一 ...