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

1. Http dio 庫(3.2.2)

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

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

而且使用簡(jiǎn)單,不過我們?cè)谑褂脮r(shí)候率碾,還是需要簡(jiǎn)單封裝叔营,便于以后切換庫。也讓代碼更加清晰易用所宰。

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

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


目錄

2. 單例

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

_httpInstance 以及 _init都是對(duì)外不可見谭羔。(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è)置.

這里簡(jiǎn)單設(shè)置了 contentType瘟裸,連接超時(shí)時(shí)間,接收超時(shí)時(shí)間诵竭,以及host ( baseUrl 的設(shè)置 )话告。相對(duì)固定的一些基礎(chǔ)參數(shù)可以直接在新建的時(shí)候設(shè)置兼搏,一些動(dòng)態(tài)的數(shù)據(jù),可以通過攔截器的形式動(dòng)態(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è)置夜矗。這里簡(jiǎn)單做一個(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;
請(qǐng)求出去之前的處理

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

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

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

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

CommonInterceptor.dart:

///可以按需要添加攔截器紊撕,實(shí)現(xiàn)一些通用的功能,例如統(tǒng)一的請(qǐ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ò)誤請(qǐng)稍后重試(" + err.response.statusCode.toString() + ")";
    } else if(null != err.request) {
      err.message = "網(wǎng)絡(luò)異常,請(qǐng)檢查網(wǎng)絡(luò)情況";
    }
    return super.onError(err);
  }
}

5. 異常封裝

dio 本來就封裝了 DioError 惭缰,不過相對(duì)來說浪南,DioError比較復(fù)雜,也不一定適合所有的需求漱受,故此络凿,做一個(gè)簡(jiǎn)單的封裝。在接收到 DioError 或者其他異常的時(shí)候昂羡,通過 Future.error 拋出絮记,自定義的異常,定義拋出信息虐先。

class HttpIOException implements Exception{

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

6. 調(diào)用

對(duì)外的調(diào)用比價(jià)簡(jiǎn)單怨愤,提供 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é)

封裝比較簡(jiǎn)單腐芍,這個(gè)也是dio本來就是一個(gè)比較完善的庫的原因差导。

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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末络断,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子项玛,更是在濱河造成了極大的恐慌貌笨,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,427評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件襟沮,死亡現(xiàn)場(chǎng)離奇詭異锥惋,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)开伏,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,551評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門膀跌,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人固灵,你說我怎么就攤上這事捅伤。” “怎么了巫玻?”我有些...
    開封第一講書人閱讀 165,747評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵丛忆,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我仍秤,道長(zhǎng)熄诡,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,939評(píng)論 1 295
  • 正文 為了忘掉前任诗力,我火速辦了婚禮凰浮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘姜骡。我一直安慰自己导坟,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,955評(píng)論 6 392
  • 文/花漫 我一把揭開白布圈澈。 她就那樣靜靜地躺著惫周,像睡著了一般。 火紅的嫁衣襯著肌膚如雪康栈。 梳的紋絲不亂的頭發(fā)上递递,一...
    開封第一講書人閱讀 51,737評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音啥么,去河邊找鬼登舞。 笑死,一個(gè)胖子當(dāng)著我的面吹牛悬荣,可吹牛的內(nèi)容都是我干的菠秒。 我是一名探鬼主播,決...
    沈念sama閱讀 40,448評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼践叠!你這毒婦竟也來了言缤?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,352評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤禁灼,失蹤者是張志新(化名)和其女友劉穎管挟,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體弄捕,經(jīng)...
    沈念sama閱讀 45,834評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡僻孝,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,992評(píng)論 3 338
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了守谓。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片穿铆。...
    茶點(diǎn)故事閱讀 40,133評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖斋荞,靈堂內(nèi)的尸體忽然破棺而出悴务,到底是詐尸還是另有隱情,我是刑警寧澤譬猫,帶...
    沈念sama閱讀 35,815評(píng)論 5 346
  • 正文 年R本政府宣布讯檐,位于F島的核電站,受9級(jí)特大地震影響染服,放射性物質(zhì)發(fā)生泄漏别洪。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,477評(píng)論 3 331
  • 文/蒙蒙 一柳刮、第九天 我趴在偏房一處隱蔽的房頂上張望挖垛。 院中可真熱鬧,春花似錦秉颗、人聲如沸痢毒。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,022評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽哪替。三九已至,卻和暖如春菇怀,著一層夾襖步出監(jiān)牢的瞬間凭舶,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,147評(píng)論 1 272
  • 我被黑心中介騙來泰國(guó)打工爱沟, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留帅霜,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,398評(píng)論 3 373
  • 正文 我出身青樓呼伸,卻偏偏與公主長(zhǎng)得像身冀,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,077評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容