Flutter dio 3.2.2 簡單封裝思路(網(wǎng)絡(luò)層)

1. Http dio 庫(3.2.2)

Flutter 里面提供了網(wǎng)絡(luò)請求的api ,不過直接使用起來會有點(diǎn)麻煩,于是有了很多第三方的網(wǎng)絡(luò)庫,dio 就是其中之一,也是相對比較成熟的庫。那為什么選 dio 呢?

官方描述: dio是一個(gè)強(qiáng)大的Dart Http請求庫,支持Restful API、FormData、攔截器、請求取消、Cookie管理、文件上傳/下載、超時(shí)、自定義適配器等

而且使用簡單,不過我們在使用時(shí)候,還是需要簡單封裝,便于以后切換庫。也讓代碼更加清晰易用。

封裝的簡單目錄結(jié)構(gòu):

一個(gè)HttpHelper 工具類,CommonInterceptor 攔截器,HttpIOException 異常封裝


目錄

2. 單例

通過dart 自帶的 factory 工廠模式,進(jìn)行單例設(shè)計(jì)。
調(diào)用是時(shí),直接 HttpUtil httpUtil = HttpUtil() 即可。

_httpInstance 以及 _init都是對外不可見。(dart 里面 _ 開頭為內(nèi)部方法、內(nèi)部變量)

class HttpUtil {
  factory HttpUtil() => _httpInstance();
  static HttpUtil _instance;
  
  static HttpUtil _httpInstance() {
    if (_instance == null) {
      _instance = HttpUtil._init();
    }
    return _instance;
  }
}

3. 基礎(chǔ)網(wǎng)絡(luò)屬性設(shè)置

dio 中基礎(chǔ)的網(wǎng)絡(luò)設(shè)置,在BaseOptions 中進(jìn)行設(shè)置.

這里簡單設(shè)置了 contentType,連接超時(shí)時(shí)間,接收超時(shí)時(shí)間,以及host ( baseUrl 的設(shè)置 )。相對固定的一些基礎(chǔ)參數(shù)可以直接在新建的時(shí)候設(shè)置,一些動態(tài)的數(shù)據(jù),可以通過攔截器的形式動態(tài)添加或設(shè)置。

設(shè)置好的參數(shù)給 new Dio 進(jìn)行dio 創(chuàng)建。

  HttpUtil._init() {
    orgOption = BaseOptions(
        contentType: CONTENT_TYPE,
        connectTimeout: CONNECT_TIMEOUT,
        receiveTimeout: RECEIVE_TIMEOUT,
        baseUrl: HOST);
    _dio = new Dio(orgOption);
  }

BaseOptions的其他參數(shù):


接收參數(shù)

4. 攔截器設(shè)置

使用過攔截器方知攔截器的重要性,攔截器多網(wǎng)絡(luò)上的處理至關(guān)重要,可以接解決很多疑難需求。

攔截器是順序調(diào)用,最先添加的先調(diào)用,后添加的后調(diào)用

dio 也提供了攔截器的設(shè)置。這里簡單做一個(gè)封裝:

  //攔截器添加
  addInterceptor(Interceptor interceptor) {
    if (null != _dio) {
      _dio.interceptors.add(interceptor);
    }
  }

  addInterceptors(List<Interceptor> interceptorList) {
    if (null != _dio) {
      _dio.interceptors.addAll(interceptorList);
    }
  }

新建攔截器

攔截器有三個(gè)方法可以實(shí)現(xiàn)攔截:、
1 . FutureOr<dynamic> onRequest(RequestOptions options) => options;
請求出去之前的處理

2 . FutureOr<dynamic> onResponse(Response response) => response;
請求結(jié)果回來的處理

3 . FutureOr<dynamic> onError(DioError err) => err;
請求發(fā)生異常時(shí)候的處理

這里新建兩個(gè)攔截器:

  1. 通用的請求頭
  2. 網(wǎng)絡(luò)錯(cuò)誤處理,做統(tǒng)一信息出來

CommonInterceptor.dart:

///可以按需要添加攔截器,實(shí)現(xiàn)一些通用的功能,例如統(tǒng)一的請求頭,統(tǒng)一的參數(shù)添加
///下面是例子

class CommonHeaderInterceptor extends Interceptor {
  @override
  FutureOr<dynamic> onRequest(RequestOptions options) {
    options.headers.addAll({
      "deviceId":"123444",
      "requestId":"ddfsgg"
    });
    return super.onRequest(options);
  }
}

class ErrorInterceptor extends Interceptor {
  @override
  FutureOr<dynamic> onError(DioError err) {
    print(err.type);//也可以區(qū)分類型,自定義message;
    if(null != err.response) {
      err.message = "網(wǎng)絡(luò)錯(cuò)誤請稍后重試(" + err.response.statusCode.toString() + ")";
    } else if(null != err.request) {
      err.message = "網(wǎng)絡(luò)異常,請檢查網(wǎng)絡(luò)情況";
    }
    return super.onError(err);
  }
}

5. 異常封裝

dio 本來就封裝了 DioError ,不過相對來說,DioError比較復(fù)雜,也不一定適合所有的需求,故此,做一個(gè)簡單的封裝。在接收到 DioError 或者其他異常的時(shí)候,通過 Future.error 拋出,自定義的異常,定義拋出信息。

class HttpIOException implements Exception{

  int code;
  String message;
  HttpIOException(this.code,this.message);
}

6. 調(diào)用

對外的調(diào)用比價(jià)簡單,提供 get post 等api 外部調(diào)用, 返回 Future<dynamic> ,進(jìn)行函數(shù)式調(diào)用返回。

如何調(diào)用:

    httpUtil.post("getServerTimestamp", getRequestData())
        .then((resp) {
          //這里可以做想要的轉(zhuǎn)換,也可以什么都不做
           HomePageResp result = new HomePageResp.fromJson(resp);
           return result;
        });

最后直接來個(gè)完整的代碼

import 'package:dio/dio.dart';
import 'dart:io';
import 'dart:async';
import 'package:move_forever_app/core/http/HttpIOExcepiton.dart';
import 'dart:convert';


const String GET = "get";
const String POST = "post";

const String HOST = "https://your_host_url.com/";
const int CONNECT_TIMEOUT = 10000;
const int RECEIVE_TIMEOUT = 3000;
final ContentType CONTENT_TYPE = ContentType.json;

typedef ErrorCallback = void Function(int count, String msg);


class HttpUtil {
  factory HttpUtil() => _httpInstance();
  static HttpUtil _instance;
  Dio _dio;
  BaseOptions orgOption;

  static HttpUtil _httpInstance() {
    if (_instance == null) {
      _instance = HttpUtil._init();
    }
    return _instance;
  }

  HttpUtil._init() {
    orgOption = BaseOptions(
        contentType: CONTENT_TYPE,
        connectTimeout: CONNECT_TIMEOUT,
        receiveTimeout: RECEIVE_TIMEOUT,
        baseUrl: HOST);
    _dio = new Dio(orgOption);
  }

  //攔截器添加
  addInterceptor(Interceptor interceptor) {
    if (null != _dio) {
      _dio.interceptors.add(interceptor);
    }
  }

  addInterceptors(List<Interceptor> interceptorList) {
    if (null != _dio) {
      _dio.interceptors.addAll(interceptorList);
    }
  }

  //post
  Future<dynamic> post (String path,postData) {
    return request(path, POST, postData);
  }

  //get
  Future<dynamic> get (String path) {
    return request(path, GET, null);
  }

  Future<dynamic> request(String path, String mode, postData) async {
    try {
      switch (mode) {
        case GET:
          var getResponse = await _dio.get(path);
          return new Future<dynamic>((){
            return getResponse.data;
          });
        case POST:
          //做一層json 轉(zhuǎn)換
          var postResponse = await _dio.post<Map<String,dynamic>>(path, data: json.encode(postData));
          return new Future<dynamic>((){
            return postResponse.data;
          });
      }
    } on DioError catch (exception) {
      return new Future.error(new HttpIOException(exception.response.statusCode, exception.message));
    } catch (error) {
      return new Future.error(new HttpIOException(-2, error.toString()));
    }
    return new Future.error(new HttpIOException(-1, "not supported"));
  }
}

7. 總結(jié)

封裝比較簡單,這個(gè)也是dio本來就是一個(gè)比較完善的庫的原因。

但是里面還有很多可以擴(kuò)展的地方,攔截器可以按需要添加,異常封裝也可以按需進(jìn)行,get post 只是最基本的請求方式,還可以對其他進(jìn)行添加封裝。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容