Flutter 使用dio来发起网络请求以及Cookie管理

逆变季风
• 阅读 13526

说点儿闲话

Flutter官方建议您使用 dio 来发起网络请求,在学习过程中,也尝试过用dart io中的HttpClient发起的请求,这里主要讲一下dio的使用以及CookieJarCookieManager管理cookie

dio

dio是一个强大易用的dart http请求库,支持Restful APIFormData、拦截器、请求取消、Cookie管理、文件上传/下载……详情请查看 github dio
最新版本请查看:pub.dev dio

pubspec.yaml文件里添加:

dio: ^3.x.x  // 请使用pub上3.0.0分支的最新版本

创建一个Dio实例,并配置它

建议在项目中使用Dio单例,这样便可对同一个dio实例发起的所有请求进行一些统一的配置,比如设置公共header、请求基地址、超时时间等;

在这里,baseUrl 需要单独创建一个共用的BaseUrl.url

class BaseUrl {
  // 配置默认请求地址
  static String url = 'http://xxxxx/'; // 测试环境
}

BaseUrl.url也方便后面Cookie管理用到。

使用默认配置:

Dio dio \= Dio(); // 使用默认配置

// 配置dio实例
dio.options.baseUrl \= BaseUrl.url;
dio.options.connectTimeout \= 5000; //5s
dio.options.receiveTimeout \= 3000;

或者

// 通过传递一个 \`options\`来创建dio实例
Options options \= BaseOptions(
    baseUrl: BaseUrl.url,
    connectTimeout: 5000,
    receiveTimeout: 3000,
);
Dio dio \= Dio(options);

发起请求及响应数据

发起一个GET请求 :

Response response;
Dio dio \= Dio();
response \= await dio.get("/test?id=12&name=wendu")
print(response.data.toString());
// 请求参数也可以通过对象传递,上面的代码等同于:
response \= await dio.get("/test", queryParameters: {"id": 12, "name": "wendu"});
print(response.data.toString());

发起一个POST请求:

response \= await dio.post("/test", data: {"id": 12, "name": "wendu"});
 try {
    Response response \= await dio.get("https://www.google.com");
    print(response.data);
    print(response.headers);
    print(response.request);
    print(response.statusCode);
  } on DioError catch (e) {
    //catch 提示
    print('catch 提示: ' + e.toString());
  } finally {
  }

CookieJar 和 CookieManager

github CookieJar
pub.dev cookie_jar

github dio_cookie_manager
pub.dev dio_cookie_manager

pubspec.yaml文件里添加:

cookie_jar: ^1.0.x  #latest version
dio_cookie_manager: ^1.0.x  #latest version
import 'package:flutter/material.dart';
import 'package:cookie_jar/cookie_jar.dart';

class Api {  
  static final CookieJar cookieJar = new CookieJar();
  
}

在项目中其他所有的dart文件中使用:


List<Cookie> cookies = [
   new Cookie("xxx", xxx),
   // ....
];
//Save cookies            
Api.cookieJar.saveFromResponse(Uri.parse(BaseUrl.url), cookies);

//获取cookies   
List<Cookie> cookies = Api.cookieJar.loadForRequest(Uri.parse(BaseUrl.url));
 // print(cookies);

需要注意的是,一般我们的项目中登录接口调用成功后,后端会在cookie中写入token,所以登录请求前先建立CookieManager来自动管理cookie:

import 'package:dio_cookie_manager/dio_cookie_manager.dart';

dio.interceptors.add(CookieManager(await Api.cookieJar));

一开始,我在app中使用的上述方法存cookie,开发过程中都是flutter run运行的,后来打包测试,发现后台杀掉app时,获取不到cookie了,这才注意到:

CookieJarcookie保存在RAM中,因此,如果应用程序退出,则将清除所有cookie

于是,改为使用下面的PersistCookieJar

PersistCookieJar

PersistCookieJar将cookie保存在文件中,因此,如果应用程序退出,则cookie始终存在,除非显式调用delete

将上述Api中的CookieJar()改为PersistCookieJar

注意:在flutter中,传递给PersistCookieJar的路径必须有效(存在于电话中并具有写访问权限)。您可以使用path_provider来获取正确的路径。

pubspec.yaml文件里添加:

path\_provider: ^1.0.x  #latest version
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:cookie_jar/cookie_jar.dart';
import 'package:path_provider/path_provider.dart';

class Api { 
  //改为使用 PersistCookieJar,在文档中有介绍,PersistCookieJar将cookie保留在文件中,因此,如果应用程序退出,则cookie始终存在,除非显式调用delete
  static PersistCookieJar _cookieJar;
  static Future<PersistCookieJar> get cookieJar async {
      // print(_cookieJar);
    if (_cookieJar == null) {
      Directory appDocDir = await getApplicationDocumentsDirectory();
      String appDocPath  = appDocDir.path;
      print('获取的文件系统目录 appDocPath: ' + appDocPath);
      _cookieJar = new PersistCookieJar(dir: appDocPath);
    }
    return _cookieJar;
  }
}

在项目中其他所有的dart文件中使用改为:

List<Cookie> cookies = [
   new Cookie("xxx", xxx),
   // ....
];
//Save cookies            
(await Api.cookieJar).saveFromResponse(Uri.parse(BaseUrl.url), cookies);

//获取cookies   
List<Cookie> cookies = (await Api.cookieJar).loadForRequest(Uri.parse(BaseUrl.url));
 // print(cookies);

建立CookieManager来自动管理cookie的代码不改变。

参考资料

dio
Http请求-Dio http库
github CookieJar
pub.dev cookie_jar
github dio_cookie_manager
pub.dev dio_cookie_manager
path_provider
Flutter用dio封装http网络请求,设置统一的请求地址、headers及处理返回内容

Post request with Cookies in Flutter

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
Jacquelyn38 Jacquelyn38
4年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Wesley13 Wesley13
3年前
FLV文件格式
1.        FLV文件对齐方式FLV文件以大端对齐方式存放多字节整型。如存放数字无符号16位的数字300(0x012C),那么在FLV文件中存放的顺序是:|0x01|0x2C|。如果是无符号32位数字300(0x0000012C),那么在FLV文件中的存放顺序是:|0x00|0x00|0x00|0x01|0x2C。2.  
Wesley13 Wesley13
3年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Wesley13 Wesley13
3年前
PHP创建多级树型结构
<!lang:php<?php$areaarray(array('id'1,'pid'0,'name''中国'),array('id'5,'pid'0,'name''美国'),array('id'2,'pid'1,'name''吉林'),array('id'4,'pid'2,'n
Easter79 Easter79
3年前
SpringBoot整合Redis乱码原因及解决方案
问题描述:springboot使用springdataredis存储数据时乱码rediskey/value出现\\xAC\\xED\\x00\\x05t\\x00\\x05问题分析:查看RedisTemplate类!(https://oscimg.oschina.net/oscnet/0a85565fa
Wesley13 Wesley13
3年前
Java日期时间API系列36
  十二时辰,古代劳动人民把一昼夜划分成十二个时段,每一个时段叫一个时辰。二十四小时和十二时辰对照表:时辰时间24时制子时深夜11:00凌晨01:0023:0001:00丑时上午01:00上午03:0001:0003:00寅时上午03:00上午0
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
1年前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这
美凌格栋栋酱 美凌格栋栋酱
5个月前
Oracle 分组与拼接字符串同时使用
SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(