Dio 封装之金屋藏娇

楔子

有这么一个纯属虚构的故事,说小王在成为老王之前,为人处事很谨慎。譬如说,他有了女朋友,他呢又想让别人知道自己有女朋友了,但是又不想让别人知道自己的女朋友是谁。很矛盾是吧?这就是小王的谨慎之处,万一哪天换女朋友了(说不定换得还挺勤快),不至于被人嘲笑乱来,或者被人称为“渣男”。

渣男

怎么办呢?小王到底是学过历史的人,想起了汉武帝刘彻年少时候的“金屋藏娇”的故事,于是就重演了这个历史。

小王的女友

小王的女友年轻漂亮,起了个英文名字叫“Dio”,据说是 pub 上的交际花,大家基本上相互联络都靠她。小王很低调,不想让别人知道她的女友是 Dio,于是对外只说自己有女朋友,并且对外宣称这个女朋友叫做 HttpUtil。目前HttpUtil其实就是披了外衣的 Dio,但是哪天小王换成别的女友了,别人也看不出来——因为从外面看,都是叫 HttpUtil。小王暗地里称之为:Dio 之金屋藏娇。

金屋藏娇

小王利用HttpUtil向外面展示了 Dio 的交际能力,譬如GetPutPostPatchDeleteUpload。这样小王很有面子,因为大家都觉得小王的女朋友很厉害——虽然没有见过面。很多年以后,小王变成老王后,老王的儿子雇佣了一批程序员,才知道程序员早就发明了这种技巧,还取了个专门的术语,叫做封装

HttpUtil

最开始的时候,小王的HttpUtil长这样。但是发现介绍女朋友的每一个交际能力都得吧啦吧啦讲一堆如何处理交际过程的尴尬场面(异常),也太麻烦了!

class HttpUtil {
  static Dio _dioInstance;
  static Dio getDioInstance() {
    if (_dioInstance == null) {
      _dioInstance = Dio();
    }

    return _dioInstance;
  }

  static Future get(String url, {Map<String, dynamic> queryParams}) async {
    try{
      return await HttpUtil.getDioInstance().get(url, queryParameters: queryParams);
    } on DioError catch (e) {
      EasyLoading.showError(e.message);
    } on Exception catch (e) {
      EasyLoading.showError(e.toString());
    }
  }
  
  //...
}

小王省事,做了一次改进,把所有的能力都通过另一个方式一起讲,这样讲的时候把全部技能都一遍的时候,只需要介绍一次如何处理尴尬场面就好了,毕竟尴尬场面的处理都是差不多的。首先,小王如数家珍似的定义了女朋友的能力。

enum HttpMethod {
  GET,
  PUT,
  POST,
  PATCH,
  DELETE,
  UPLOAD,
}

接着,定义了他介绍女朋友的话术:

static Future sendRequest(HttpMethod method, String url,
      {Map<String, dynamic> queryParams, dynamic data}) async {
  try {
    switch (method) {
      case HttpMethod.GET:
        return await HttpUtil.getDioInstance()
            .get(url, queryParameters: queryParams);
      case HttpMethod.PUT:
        return await HttpUtil.getDioInstance()
            .put(url, queryParameters: queryParams, data: data);
      case HttpMethod.POST:
        return await HttpUtil.getDioInstance()
            .post(url, queryParameters: queryParams, data: data);
      case HttpMethod.PATCH:
        return await HttpUtil.getDioInstance()
            .patch(url, queryParameters: queryParams, data: data);
      case HttpMethod.DELETE:
        return await HttpUtil.getDioInstance()
            .delete(url, queryParameters: queryParams, data: data);
      default:
        EasyLoading.showError('请求方式错误');
    }
  } on DioError catch (e) {
    EasyLoading.showError(e.message);
  } on Exception catch (e) {
    EasyLoading.showError(e.toString());
  }

  return null;
}

这个时候,再来介绍某一项能力就轻松多了。

static Future get(String url, {Map<String, dynamic> queryParams}) async {
    return await sendRequest(HttpMethod.GET, url, queryParams: queryParams);
  }

static Future put(String url,
    {Map<String, dynamic> queryParams, dynamic data}) async {
  return await sendRequest(HttpMethod.PUT, url,
      queryParams: queryParams, data: data);
}

static Future post(String url,
    {Map<String, dynamic> queryParams, dynamic data}) async {
  return await sendRequest(HttpMethod.POST, url,
      queryParams: queryParams, data: data);
}

static Future patch(String url,
    {Map<String, dynamic> queryParams, dynamic data}) async {
  return await sendRequest(HttpMethod.PATCH, url,
      queryParams: queryParams, data: data);
}

static Future delete(String url,
    {Map<String, dynamic> queryParams, dynamic data}) async {
  return await sendRequest(HttpMethod.DELETE, url,
      queryParams: queryParams, data: data);
}

static Future uploadSingle(String url, String fileKey, File file,
    {Map<String, dynamic> queryParams}) async {
  FormData formData = FormData.fromMap({
    fileKey: await MultipartFile.fromFile(file.path),
  });
  return await sendRequest(HttpMethod.POST, url,
      queryParams: queryParams, data: formData);
}
轻松搞定

外面的世界

一切就绪,小王开始切断了女朋友 Dio 与外界的联系,从此外面的世界的人只知道小王有个女朋友,代号叫 HttpUtil,至于到底是谁,长得怎么样,全靠小王的一张嘴了!比如DynamicService这位同学:

import '../utils/http_util.dart';

class DynamicService {
  static String host = 'http://localhost:3900/api/';
  static Future list(page, pageSize) async {
    var result = await HttpUtil.get(
      host + 'dynamics',
      queryParams: {'page': page, 'pageSize': pageSize},
    );

    return result;
  }

  static Future get(String id) async {
    var result = await HttpUtil.get(
      host + 'dynamics/' + id,
    );

    return result;
  }

  static Future post(Map<String, dynamic> data) async {
    var result = await HttpUtil.post(host + 'dynamics', data: data);

    return result;
  }

  static Future updateAll(String id, Map<String, dynamic> data) async {
    var result = await HttpUtil.put(host + 'dynamics/' + id, data: data);

    return result;
  }

  static Future update(String id, Map<String, dynamic> data) async {
    var result = await HttpUtil.patch(host + 'dynamics/' + id, data: data);

    return result;
  }

  static Future updateViewCount(String id) async {
    var result = await HttpUtil.patch(host + 'dynamics/view/' + id);

    return result;
  }

  static Future delete(String id) async {
    var result = await HttpUtil.delete(
      host + 'dynamics/' + id,
    );

    return result;
  }
}

再比如 DynamicAdd 这位同学:

//...
var response = await DynamicService.post(newFormData);
if (response != null && response.statusCode == 200) {
  Dialogs.showInfo(context, '添加成功');
  GetIt.instance
      .get<DynamicListener>()
      .dynamicAdded(DynamicEntity.fromJson(response.data));
  Navigator.of(context).pop();
} else {
  Dialogs.showInfo(this.context,
      response?.statusMessage != null ? response.statusMessage : '添加失败');
}
//...

结局

小王给外面人的形象是愈发神秘了,大家都想见见小王的能干女友,可是每次小王讲的都是 HttpUtil,而他自己呢也很满意自己的这个“金屋藏娇”的主意,直到有一天他成为老王后,他家的儿子——新的小王给他捅了篓子。

——未完待续

知识点梳理

  • 封装:对于第三方插件,我们不排除以后可能会更换,因此最好的方式是将第三方插件进行封装,隐藏具体的实现细节,这样假设我们以后需要更换插件,只需要该封装类即可,而不是让第三方插件散落在各个模块里,这样改起来非常痛苦,而且容易遗漏。——譬如我们将之前的网络请求代码更改,就需要一个个文件修改。
  • async/await 补充:调用网络请求时,使用 await 会等待结果返回,如果不使用await的话,会出现异步执行情况,结果就是异常捕获代码不起作用。大家可以试一下,在HttpUtil取消 await后,将后台服务停止的效果。

源码已上传至Dio 封装源代码

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,921评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,635评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,393评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,836评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,833评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,685评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,043评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,694评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,671评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,670评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,779评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,424评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,027评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,984评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,214评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,108评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,517评论 2 343

推荐阅读更多精彩内容