Flutter 请求网络的三种方式

flutter 请求网络的方式有三种,分别是 Dart 原生的网络请求 HttpClient、第三方网络请求 http以及 Flutter 中的 Dio。我们可以比较一下这三种网络请求方式,然后封装为我们方便请求网络的工具类。

Dart 原生的网络请求 HttpClient

实现 Dart 获取网络数据的请求,一般我们需要以下几个步骤:

原生的网络请求时不需要修改 pubspec.yaml 文件的,我们只需要在使用的地方引入所需包就可以了

導入
import 'dart:convert';
import 'dart:io';
void _httpClient() async{
//创建一个HttpClient
HttpClient httpClient = new HttpClient();
//携带参数的请求
/*Uri uri=Uri(scheme: "https", host: "flutterchina.club", queryParameters: {
"userName":"chen",
"password":"123456"
});*/
var url = 'http://47.100.106.80:8080/Test/all';
//打开Http连接,设置请求头
HttpClientRequest request = await httpClient.getUrl(Uri.parse(url));
//设置请求的 header
request.headers.add("user-agent", "test");
request.headers.add("Authorization", "LKSJDLFJSDLKJSLKklsdj");
//等待连接服务器
HttpClientResponse response = await request.close();
//读取响应内容
if (response.statusCode == HttpStatus.ok) {
var data = await response.transform(Utf8Decoder()).join();
print(data);
}
//断开连接
//httpClient.close();
}

第三方HTTP

添加依賴

http: ^0.11.0

導入包

import 'package:http/http.dart' as http;

get請求

//异步加载数据
void _getRequest() async {
//下面为具体网址,需要自己修改
String url = "http://47.100.106.80:8080/Test/all";
var client = http.Client();
http.Response response = await client.get(url);
setState(() {
final data = json.encode(response.body);
print('data:'+data);
});
} //初始化状态
@override
void initState() {
super.initState();
_getRequest();
}

post

//异步加载数据
void _postRequest() async {
String url = "http://47.100.106.80:8080/Test/add";
var client = http.Client();
var params = Map<String,String>();
params['name'] = '測試數據'; http.Response response = await client.post(url,body:params);
setState(() {
final data = json.encode(response.body);
print(data);
});
}

Flutter 发布的 dio

Dio 一个强大的 Dart Http 请求库,支持 Restful API、FormData、拦截器、请求取消、Cookie管理、文件上传/下载、超时等...

添加依賴

dependencies:
dio: ^1.0.9

導入

import 'package:dio/dio.dart';

get請求

void getRequest() async {
Dio dio = new Dio();
var response = await dio.get("http://47.100.106.80:8080/Test/all");
final data = response.data.toString();
print(data);
}

post請求

void postRequest() async {
var dio = new Dio();
var response = await dio.post("http://47.100.106.80:8080/Test/add", data:{"name":"name1","account":"測試數據212312"});
final data = response.data.toString();
print(response);
print(data);
}

參考:https://www.jianshu.com/p/3080e0b81cf4

Dio 网络请求框架封装

日志信息拦截

Dio 和 okhttp 一样,都会有一个请求拦截器和响应拦截器,通过拦截器,我们可以在请求之前或响应之后做一些同意的预处理。例如我们发起请求前查看我们请求的参数和头部,响应的时候,我们可以查看返回来的数据。

Dio dio = new Dio();
// 添加拦截器
if (Config.DEBUG) {
dio.interceptors.add(InterceptorsWrapper(
onRequest: (RequestOptions options){
print("\n================== 请求数据 ==========================");
print("url = ${options.uri.toString()}");
print("headers = ${options.headers}");
print("params = ${options.data}");
},
onResponse: (Response response){
print("\n================== 响应数据 ==========================");
print("code = ${response.statusCode}");
print("data = ${response.data}");
print("\n");
},
onError: (DioError e){
print("\n================== 错误响应数据 ======================");
print("type = ${e.type}");
print("message = ${e.message}");
print("stackTrace = ${e.stackTrace}");
print("\n");
}
));
}

如果我们想要移除拦截器,那么我们可以将其设置为 null

dio.interceptor.request.onSend=null;
dio.interceptor.response.onSuccess=null;
dio.interceptor.response.onError=null;

token 添加

    //  头部添加 token 验证
headers["Authorization"] = "token lskjdlklsjkdklsjd333";
option.headers = headers;
///超时
option.connectTimeout = 15000;
try {
Response response = await dio.request(url, data: params, options: option);
} on DioError catch (e) {
// 请求错误处理
}

自动生成 dart 的 json 实体类插件 FlutterJsonBeanFactory

在 Android 开发中,有 GsonFormat 这个插件来讲 json 数据自动转化成 Bean;那么在 Flutter 中也有类似的插件可以生产序列化的实体类的插件:FlutterJsonBeanFactory

  • step 1:下载插件 FlutterJsonBeanFactory,安装完成后重启
Setting -> Plugins -> Browse Respositories 中搜索 FlutterJsonBeanFactory
  • step 2:创建实体类,在指定目录下:
New -> dart bean class File from JSON
 
jsontobean.png
  • step 3:输入实体类名及 json 格式的数据

     
    format.png
  • step 4:最后生成的实体类:LoginEntity

class LoginEntity {
String easemobpassword;
String username; LoginEntity({this.easemobpassword, this.username}); LoginEntity.fromJson(Map<String, dynamic> json) {
easemobpassword = json['easemobPassword'];
username = json['username'];
} Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['easemobPassword'] = this.easemobpassword;
data['username'] = this.username;
return data;
}
}

请求错误处理

Response response;
try {
response = await dio.request(url, data: params, options: option);
} on DioError catch (e) {
// 请求错误处理
Response errorResponse;
if (e.response != null) {
errorResponse = e.response;
} else {
errorResponse = new Response(statusCode: 666);
}
if (e.type == DioErrorType.CONNECT_TIMEOUT) {
errorResponse.statusCode = Code.NETWORK_TIMEOUT;
}
if (Config.DEBUG) {
print('请求异常: ' + e.toString());
print('请求异常 url: ' + url);
}
return new ResultData(Code.errorHandleFunction(errorResponse.statusCode, e.message, noTip), false, errorResponse.statusCode);
}

其中 ResultData 是网络结果处理的实体类

/**
* 网络结果数据
* Created by chenjianrun
* Date: 2018-07-16
*/
class ResultData {
var data;
bool result;
int code;
var headers; ResultData(this.data, this.result, this.code, {this.headers});
}

Code 是处理网络错误的编码,并将错误结果通过 eventbus 发送出去,一般我们可以在 main_pager 中注册监听这个事件。

///网络请求错误编码
class Code {
///网络错误
static const NETWORK_ERROR = -1; ///网络超时
static const NETWORK_TIMEOUT = -2; ///网络返回数据格式化一次
static const NETWORK_JSON_EXCEPTION = -3; static const SUCCESS = 200; static final EventBus eventBus = new EventBus(); static errorHandleFunction(code, message, noTip) {
if(noTip) {
return message;
}
eventBus.fire(new HttpErrorEvent(code, message));
return message;
}
}

完成的网络请求类:HttpRequest

import 'dart:io';

import 'package:dio/dio.dart';
import 'package:private_tutor/common/SpUtils.dart';
import 'package:connectivity/connectivity.dart'; import 'dart:collection'; import 'package:private_tutor/common/config/Config.dart';
import 'package:private_tutor/net/ResultCode.dart';
import 'package:private_tutor/net/ResultData.dart'; ///http请求管理类,可单独抽取出来
class HttpRequest {
static String _baseUrl;
static const CONTENT_TYPE_JSON = "application/json";
static const CONTENT_TYPE_FORM = "application/x-www-form-urlencoded";
static Map optionParams = {
"timeoutMs": 15000,
"token": null,
"authorizationCode": null,
}; static setBaseUrl(String baseUrl){
_baseUrl = baseUrl;
} static get(url,param) async{
return await request(_baseUrl+url, param, null, new Options(method:"GET"));
} static post(url,param) async{
return await request(_baseUrl+url, param, {"Accept": 'application/vnd.github.VERSION.full+json'}, new Options(method: 'POST'));
} static delete(url,param) async{
return await request(_baseUrl+url, param, null, new Options(method: 'DELETE'));
} static put(url,param) async{
return await request(_baseUrl+url, param, null, new Options(method: "PUT", contentType: ContentType.text));
} ///发起网络请求
///[ url] 请求url
///[ params] 请求参数
///[ header] 外加头
///[ option] 配置
static request(url, params, Map<String, String> header, Options option, {noTip = false}) async { //没有网络
var connectivityResult = await (new Connectivity().checkConnectivity());
if (connectivityResult == ConnectivityResult.none) {
return new ResultData(Code.errorHandleFunction(Code.NETWORK_ERROR, "", noTip), false, Code.NETWORK_ERROR);
} Map<String, String> headers = new HashMap();
if (header != null) {
headers.addAll(header);
} //授权码
if (optionParams["authorizationCode"] == null) {
var authorizationCode = await getAuthorization();
if (authorizationCode != null) {
optionParams["authorizationCode"] = authorizationCode;
}
} headers["Authorization"] = optionParams["authorizationCode"];
// 设置 baseUrl if (option != null) {
option.headers = headers;
} else{
option = new Options(method: "get");
option.headers = headers;
} ///超时
option.connectTimeout = 15000; Dio dio = new Dio();
// 添加拦截器
if (Config.DEBUG) {
dio.interceptors.add(InterceptorsWrapper(
onRequest: (RequestOptions options){
print("\n================== 请求数据 ==========================");
print("url = ${options.uri.toString()}");
print("headers = ${options.headers}");
print("params = ${options.data}");
},
onResponse: (Response response){
print("\n================== 响应数据 ==========================");
print("code = ${response.statusCode}");
print("data = ${response.data}");
print("\n");
},
onError: (DioError e){
print("\n================== 错误响应数据 ======================");
print("type = ${e.type}");
print("message = ${e.message}");
print("stackTrace = ${e.stackTrace}");
print("\n");
}
));
} Response response;
try {
response = await dio.request(url, data: params, options: option);
} on DioError catch (e) {
// 请求错误处理
Response errorResponse;
if (e.response != null) {
errorResponse = e.response;
} else {
errorResponse = new Response(statusCode: 666);
}
if (e.type == DioErrorType.CONNECT_TIMEOUT) {
errorResponse.statusCode = Code.NETWORK_TIMEOUT;
}
if (Config.DEBUG) {
print('请求异常: ' + e.toString());
print('请求异常 url: ' + url);
}
return new ResultData(Code.errorHandleFunction(errorResponse.statusCode, e.message, noTip), false, errorResponse.statusCode);
} try {
if (option.contentType != null && option.contentType.primaryType == "text") {
return new ResultData(response.data, true, Code.SUCCESS);
} else {
var responseJson = response.data;
if (response.statusCode == 201 && responseJson["token"] != null) {
optionParams["authorizationCode"] = 'token ' + responseJson["token"];
await SpUtils.save(Config.TOKEN_KEY, optionParams["authorizationCode"]);
}
}
if (response.statusCode == 200 || response.statusCode == 201) {
return ResultData(response.data, true, Code.SUCCESS, headers: response.headers);
}
} catch (e) {
print(e.toString() + url);
return ResultData(response.data, false, response.statusCode, headers: response.headers);
}
return new ResultData(Code.errorHandleFunction(response.statusCode, "", noTip), false, response.statusCode);
} ///清除授权
static clearAuthorization() {
optionParams["authorizationCode"] = null;
SpUtils.remove(Config.TOKEN_KEY);
} ///获取授权token
static getAuthorization() async {
String token = await SpUtils.get(Config.TOKEN_KEY);
if (token == null) {
String basic = await SpUtils.get(Config.USER_BASIC_CODE);
if (basic == null) {
//提示输入账号密码
} else {
//通过 basic 去获取token,获取到设置,返回token
return "Basic $basic";
}
} else {
optionParams["authorizationCode"] = token;
return token;
}
}
}

使用示例

/// 登录 model
class LoginModel{
// 手机号码登录
static phoneLogin(String phone,String verifyCode) async{
ResultData response = await HttpRequest.post(Address.phoneLogin, {"phoneNum" : phone,"captcha":verifyCode});
if(response != null && response.result){
PhoneLoginEntity phoneLoginEntity = PhoneLoginEntity.fromJson(json.decode(response.data));
return new DataResult(phoneLoginEntity, true);
}else{
return new DataResult(null, false);
}
} // 获取验证码
static getVerifyCode(String phone) async{
ResultData response = await HttpRequest.get("${Address.getVerifyCode}?phone=${phone}", null); // var response = await HttpRequest.get(Address.getVerifyCode, {"phone":phone});
if(response != null && response.result){
VerifyCodeEntity entity = VerifyCodeEntity.fromJson(response.data);
return new DataResult(entity, true);
}else{
return new DataResult(null, false);
}
}
}

Flutter-網絡請求的更多相关文章

  1. jquery easyui 1.3.4 datagrid pageNumber 設置導致兩次請求的解决方案

    $('#table').datagrid({ url: '/get/data/path/to/your/server', pageNumber: , pageSize: , ... }); 當手動設置 ...

  2. Flask從入門到入土(二)——請求响应與Flask扩展

    ———————————————————————————————————————————————————————————— 一.程序和請求上下文 Flask從客戶端收到請求時,要讓視圖函數能訪問一些對象 ...

  3. HTTP請求

    HTTP[超文本傳輸協議]是因特網上應用最為廣泛的一種網絡傳輸協議,送油的WWW文件都必須遵守這個標準. HTTP是一個基於TCP/IP通信協議來產地數據(html文件,圖片文件,查詢結果等). HT ...

  4. iPhone6手機產品提交了進網申請

    近期,海外投資蘋果公司為iPhone6手機產品提交了進網申請,經電信設備進網檢測機構測試和我部審查,相關產品滿足進網管理要求.根據<電信條例>有關規定,我部依法定程式在法定時限內為蘋果公司 ...

  5. 3G網絡容量和業務承載的壓力大大增加!

    在移動通信話音業務繼續保持發展的同時,對IP和高速數據業務的支持已經成為移動通信系統演進的方向.移動數據業務是推動目前移動通信技術發展的主要動力,TD-LTE作為準4G技術,以提高數據速率和頻譜利用率 ...

  6. ionic 向後台請求json 數據 在頁面上的顯示問題

    我向服務器請求數據,獲取到的數據竟然不能顯示在頁面上  我那個氣啊..... <ul> <!-- <li ng-repeat="phone in phones&quo ...

  7. bzoj 1305: [CQOI2009]dance 二分+網絡流判定

    1305: [CQOI2009]dance跳舞 Time Limit: 5 Sec  Memory Limit: 162 MBSubmit: 1340  Solved: 581[Submit][Sta ...

  8. BZOJ1001[BeiJing2006]狼抓兔子最小割網絡流

    Description 现在小朋友们最喜欢的"喜羊羊与灰太狼",话说灰太狼抓羊不到,但抓兔子还是比较在行的, 而且现在的兔子还比较笨,它们只有两个窝,现在你做为狼王,面对下面这样一 ...

  9. JavaScript使用XMLHttpRequest 發送GET/Post 請求

    <!DOCTYPE HTML> <html> <head> <title>Demo</title> <script type=&quo ...

随机推荐

  1. spring- junit测试事务回滚

    http://blog.csdn.net/molingduzun123/article/details/49383235

  2. php WebSocket 简单实现demo

    WebSocket 是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议. WebSocket 使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据. 在 ...

  3. telnet测试端口是否打开?

    如何测试远程服务器的某个端口是否打开? 例如: telnet 192.168.1.1 5000 返回: Trying 127.0.0.1...Connected to 127.0.0.1.Escape ...

  4. centos 6.9 mysql 安装配置

    1.全新系统,安装mysql yum -y install mysql mysql-server mysql-devel 2.启动mysql service mysqld start 3.修改密码 登 ...

  5. HDFS——完全分布式搭建

    架构 NN--namenode SNN--secondnamenode DN--datanode hadoop_env.sh中修改JAVA_HOME core-site.xml <propert ...

  6. vCenter 部件关系简介 & 网络原理

    目录 目录 主机和集群 vCenter Datacenter Cluster Host Virtual Machine Folder Resource Pool Template 数据存储 Datas ...

  7. clientdataset 读取excel 如果excel 文件不存在的时候 相应的gird 会不显示数据, 鼠标掠过 gird 格子 才会显示数据。 这是一个bug 哈哈

    clientdataset 读取excel   如果excel 文件不存在的时候   相应的gird 会不显示数据, 鼠标掠过 gird 格子 才会显示数据.   这是一个bug 哈哈

  8. 观察者模式(jdk实现)

    1.定义 在对象中定义一对多的依赖,当一个对象改变状态,依赖它的对象会收到通知并更新. 2.实现   (主要通过jdk自己定义的观察者实现) 以气象站通知展示板为例子,当气象站收到的各种参数改变的时候 ...

  9. 尝试Vue3.0

    Composition API 纯函数式 <!DOCTYPE html> <html lang="en"> <head> <meta ch ...

  10. MongoDB查询系统

    首先,我们先向集合(collections)中添加测试文档(documents).如下: > for(i=1;i<=5;i++) db.test.insert({x:i,y:i*i,z:6 ...