不得不說的DIO

Flutter網絡框架DIO的基本使用

1.基本概念

dio是一個強大的Dart Http請求庫,支持Restful API、FormData、攔截器、請求取消、Cookie管理、文件上傳/下載、超時、自定義適配器等...html

2.簡單示例代碼

import 'package:dio/dio.dart';
main() async {
  var dio = Dio();
  Response response = await dio.get("https://google.com");
  print(response.data);
}
複製代碼

3.添加依賴

在pubspec.yaml文件中添加:git

dependencies:
  dio: 2.1.13  #當前最新版本爲2.1.13
  
複製代碼

4.DIO常見內容列表

  • 使用application/x-www-form-urlencoded編碼
默認狀況下, Dio 會將請求數據(除過String類型)序列化爲 JSON. 若是想要以 application/x-www-form-urlencoded格式編碼, 你能夠顯式設置contentType :
複製代碼
//Instance level
dio.options.contentType=ContentType.parse("application/x-www-form-urlencoded");
//or works once
dio.post("/info",data:{"id":5}, options: new Options(contentType:ContentType.parse("application/x-www-form-urlencoded")));
複製代碼
  • 請求示例(get、post)github

    一、發起get請求json

    Response response;
    Dio dio = new 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請求api

    • 普通post方式
    response = await dio.post("/test", data: {"id": 12, "name": "wendu"});
    複製代碼
    • FormData的post請求方式: Dio支持發送 FormData, 請求數據將會以 multipart/form-data方式編碼, FormData中能夠一個或多個包含文件

    注意: 只有 post 方法支持發送 FormData.數組

    FormData formData = new FormData.from({
     "name": "wendux",
     "age": 25,
    });
    response = await dio.post("/info", data: formData);
    複製代碼
    • FormData上傳多個文件
    FormData formData = new FormData.from({
    "name": "wendux",
    "age": 25,
    "file1": new UploadFileInfo(new File("./upload.txt"), "upload1.txt"),
    //支持直接上傳字節數組 (List<int>) ,方便直接上傳內存中的內容
    "file2": new UploadFileInfo.fromBytes(
        utf8.encode("hello world"), "word.txt"),
    // 支持文件數組上傳
    "files": [
        new UploadFileInfo(new File("./example/upload.txt"), "upload.txt"),
        new UploadFileInfo(new File("./example/upload.txt"), "upload.txt")
    ]
    });
    response = await dio.post("/info", data: formData);
    複製代碼

    三、發起併發請求bash

    response = await Future.wait([dio.post("/info"), dio.get("/token")]);
    複製代碼

    四、下載文件服務器

    response = await dio.download("https://www.google.com/", "./xx.html");
    複製代碼

    五、請求接收方式markdown

    • a.形式接收
    Response<ResponseBody> rs = await Dio().get<ResponseBody>(url,
    options: Options(responseType: ResponseType.stream), //設置接收類型爲stream);
    print(rs.data.stream); //響應流
    複製代碼
    • b.二進制接收
    Response<List<int>> rs = await Dio().get<List<int>>(url,
    options: Options(responseType: ResponseType.bytes), //設置接收類型爲bytes);
    print(rs.data); //二進制數組
    複製代碼

    6.監聽發送(上傳)數據速度cookie

    response = await dio.post(
    "http://www.dtworkroom.com/doris/1/2.0.0/test",
    data: {"aa": "bb" * 22},
    onSendProgress: (int sent, int total) {
    print("$sent $total");
    },
    );
    複製代碼

    7.以的形式提交二進制數據

    // 二進制數據
    List<int> postData = <int>[...];
    await dio.post(
    url,
    data: Stream.fromIterable(postData.map((e) => [e])), //建立一個Stream<List<int>>
    options: Options(
        headers: {
        HttpHeaders.contentLengthHeader: postData.length, // 設置content-length
        },
    ),
    );
    若是要監聽提交進度,則必須設置content-length,反之則是可選的。
    複製代碼
  • Dio APIs

DIO核心API代碼以下:

Future request(String path, {data,Map queryParameters, Options options,CancelToken cancelToken, ProgressCallback onSendProgress, ProgressCallback onReceiveProgress)

    response = await request(
        "/test",
        data: {"id": 12, "name": "xx"},
        options: Options(method: "GET"),
    );
複製代碼

建議在項目中使用Dio單例,這樣即可對同一個dio實例發起的全部請求進行一些統一的配置,好比設置公共header、請求基地址、超時時間等

咱們能夠使用默認配置或傳遞一個可選BaseOptions參數來建立一個Dio實例

Dio dio = new Dio(); // 使用默認配置
    // 配置dio實例
    dio.options.baseUrl = "https://www.xx.com/api";
    dio.options.connectTimeout = 5000; //5s
    dio.options.receiveTimeout = 3000;

    // 或者經過傳遞一個 `BaseOptions`來建立dio實例
    BaseOptions options = new BaseOptions(
        baseUrl: "https://www.xx.com/api",
        connectTimeout: 5000,
        receiveTimeout: 3000,
    );
    Dio dio = new Dio(options);
複製代碼
  • 請求配置

下面是全部的請求配置選項。 若是請求method沒有指定,則默認爲GET :

{
  /// Http method.
  String method;

  /// 請求基地址,能夠包含子路徑,如: "https://www.google.com/api/".
  String baseUrl;

  /// Http請求頭.
  Map<String, dynamic> headers;

  /// 鏈接服務器超時時間,單位是毫秒.
  int connectTimeout;
  /// 2.x中爲接收數據的最長時限.
  int receiveTimeout;

  /// 請求路徑,若是 `path` 以 "http(s)"開始, 則 `baseURL` 會被忽略; 不然,
  /// 將會和baseUrl拼接出完整的的url.
  String path = "";

  /// 請求的Content-Type,默認值是[ContentType.JSON].
  /// 若是您想以"application/x-www-form-urlencoded"格式編碼請求數據,
  /// 能夠設置此選項爲 `ContentType.parse("application/x-www-form-urlencoded")`, 這樣[Dio]
  /// 就會自動編碼請求體.
  ContentType contentType;

  /// [responseType] 表示指望以那種格式(方式)接受響應數據。
  /// 目前 [ResponseType] 接受三種類型 `JSON`, `STREAM`, `PLAIN`.
  ///
  /// 默認值是 `JSON`, 當響應頭中content-type爲"application/json"時,dio 會自動將響應內容轉化爲json對象。
  /// 若是想以二進制方式接受響應數據,以下載一個二進制文件,那麼能夠使用 `STREAM`.
  ///
  /// 若是想以文本(字符串)格式接收響應數據,請使用 `PLAIN`.
  ResponseType responseType;

  /// `validateStatus` 決定http響應狀態碼是否被dio視爲請求成功, 返回`validateStatus`
  /// 返回`true` , 請求結果就會按成功處理,不然會按失敗處理.
  ValidateStatus validateStatus;

  /// 用戶自定義字段,能夠在 [Interceptor]、[Transformer] 和 [Response] 中取到.
  Map<String, dynamic> extra;

  /// 公共query參數
  Map<String, dynamic /*String|Iterable<String>*/ > queryParameters;
}

複製代碼
  • 響應數據

當請求成功時會返回一個Response對象,它包含以下字段

{
  /// 響應數據,可能已經被轉換了類型, 詳情請參考Options中[ResponseType].
  var data;
  /// 響應頭
  HttpHeaders headers;
  /// 本次請求信息
  Options request;
  /// Http status code.
  int statusCode;
  /// 是否重定向
  bool isRedirect;  
  /// 重定向信息 
  List<RedirectInfo> redirects ;
  /// 最終真正的請求地址(由於可能會重定向)
  Uri realUri;   
  /// 響應對象的自定義字段(能夠在攔截器中設置它),調用方能夠在`then`中獲取.
  Map<String, dynamic> extra;

  //注:假若有一個url返回的是json數據,返回數據在默認狀況下(options.responseType爲json)會被自動轉爲Json對象(Map或List)的:
}
複製代碼

以請求Google爲例:

Response response = await dio.get("https://www.google.com");
  print(response.data);
  print(response.headers);
  print(response.request);
  print(response.statusCode);
複製代碼
  • 攔截器

咱們在網絡請求中每每須要查看日誌信息,此時就須要添加一個日誌攔截器

dio.interceptors.add(LogInterceptor(responseBody: false)); //開啓請求日誌
複製代碼
在添加攔截器時須要注意,因爲攔截器隊列的執行順序是FIFO,若是把log攔截器添加到了最前面,則後面攔截器對options的更改就不會被打印(但依然會生效),因此建議把log攔截添加到隊尾。
複製代碼
  • Cookie管理

有時在進行請求中須要攔截cookie來自動管理請求/響應cookie,那麼就須要添加依賴

dependencies:
  cookie_jar: ^1.0.1
複製代碼
你能夠建立一個CookieJar 或 PersistCookieJar 來幫您自動管理cookie, dio 默認使用 CookieJar , 它會將cookie保存在內存中。
若是您想對cookie進行持久化, 請使用 PersistCookieJar , 示例代碼以下:
var dio = new Dio();
dio.interceptors.add(CookieManager(CookieJar()))
複製代碼

廣泛說來,若是須要建立一些自定義的攔截器,只須要經過繼承Intercepto類來實現便可

  • 錯誤處理

當請求過程當中發生錯誤時, Dio 會包裝 Error/Exception 爲一個 DioError:

try {
    //404
    await dio.get("https://wendux.github.io/xsddddd");
  } on DioError catch (e) {
    // The request was made and the server responded with a status code
    // that falls out of the range of 2xx and is also not 304.
    if (e.response) {
      print(e.response.data);
      print(e.response.headers);
      print(e.response.request);
    } else {
      // Something happened in setting up or sending the request that triggered an Error
      print(e.request);
      print(e.message);
    }
  }
複製代碼

DioError字段

{
  /// 響應信息, 若是錯誤發生在在服務器返回數據以前,它爲 `null`
  Response response;

  /// 錯誤描述.
  String message;

  /// 錯誤類型,見下文
  DioErrorType type;

  ///原始的error或exception對象,一般type爲DEFAULT時存在。
  dynamic error;

  /// 錯誤棧信息,可能爲null
  StackTrace stackTrace;
}
複製代碼
  • 設置Http代理
(dio.httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate = (client) {
    // config the http client
    client.findProxy = (uri) {
        //proxy all request to localhost:8888
        return "PROXY localhost:8888";
    };
    // you can also create a new HttpClient to dio
    // return new HttpClient();
};
複製代碼
  • 請求取消

能夠經過 cancel token 來取消發起的請求:

CancelToken token = new CancelToken();
dio.get(url, cancelToken: token)
    .catchError((DioError err){
        if (CancelToken.isCancel(err)) {
            print('Request canceled! '+ err.message)
        }else{
            // handle error.
        }
    });
// cancel the requests with "cancelled" message.
token.cancel("cancelled");
複製代碼
相關文章
相關標籤/搜索