需求背景

继上篇《Flutter 下载篇 - 壹 | flutter_download_manager 源码解析》中详细介绍了 flutter_download_manager 用法和原理。在优缺点中提到,该库纯 Dart 实现,支持下载管理,暂停,恢复,取消和断点续传。其中有个缺点是网络库与 dio 强耦合,不支持自定义网络库扩展。

有人会说: dio 这么牛逼,直接用不就好了,为啥还要支持别的网络库,没事别瞎折腾。

我想说:

  1. 世界不只有一种声音,那不然多无趣。
  2. 第三方库对应用本身来说是黑盒,开发者一般疏于关注其功能改动对应用影响除非产生重大事故,这种不可控的情况应谨慎。
  3. 设计上遵循 DIP 原则,抽象不要依赖具体实现细节,具体细节依赖抽象,我们需要抽象网络层来给项目依赖而非直接依赖 dio。
  4. 快速切换到其他网路库。

本文将从现状出发,一步步带你解耦 flutter_download_manager 中的网络库。

现状说明

从类图上整体了解 flutter_download_manager 类设计过程中对 dio 强耦合概括,然后通过代码具体讲解。

类图体现

代码体现

耦合点一:dio.CancelToken

每个下载任务请求中都会使用到 dio:CancelToken 通过 dio 网络库间接实现任务的取消功能。

耦合点二:dio.download

cancelToken.cancel() 算依赖 CancelToken

如上简写代码中调用链关系,最终调用链及对 dio 依赖关系总结:

下载库对 dio 的依赖在于: CancelToken 和 download 方法

如何定制网络库

通过上述对现状分析总结,结合设计基本原则:封装变化将不变从变化中隔离出来。其中变化的就是网络库的下载,CancelToken 和取消功能。只用封装这部分变化,将网络库下载和 Token 抽象出来进行封装。

1. 网络层设计

目的:让 flutter_download_manager 与 dio.download 解耦。

思路:将网络相关操作抽象成接口,依赖注入到 downloadManager 对象中。

实施步骤

  1. 抽象网络层接口

考虑到 download 返回 Future 中对象问题,因为会用到 response.statusCode,这里直接用 dynamic 来,具体可以细化成封装成 DownloadResponse,其中包含 statusCode 属性。

  1. customhttpclient 通过依赖注入传入 DownloadManager,让其不依赖具体实现而依赖抽象,依赖注入实现对象之间的组合关系提高扩展性。

2. CancelToken 设计

目的:让 flutter_download_manager 与 dio.CancelToken 解耦。

思路:CancelToken 与取消息息相关,而且必须提供一个 cancel 方法来供 downloadmanager 中暂停等方法使用。考虑到每个 custom_http_client 的 CancelToken 结构体存在不一样,而 cancel 方法命名多样性原则,这里设计一个统一的 DownloadCancelToken 接口,提供 cancel 方法,将其中实现代理给具体网络库的 CancelToken 对象。

实施步骤

  1. 抽象一个 Token 对象并提供 cancel 方法,并实现一个默认代理其他网络库的 Proxy 类。

小技巧: 用 Function.apply 是因为它本身支持位置参数和可选参数传入。

  1. custom_http_client 中抽象一个 DownloadCancelToken 抽象接口供外部使用

3. 下载器设计

目的:下载器与具体实现 downloadmanager 解耦

思路:downloadmanager 中提供了 addDownload 等下载通用方法及下载管理逻辑抽象。这块存在变化可以有多种实现,也抽象下。

实施步骤:

  1. 下载器抽象成接口

  1. downloadManager 依赖 IDownloader

至此,可定制网络库改造已全部完成,接下来就可以隔离 dio 网络实现了。

网络库隔离效果

通过依赖注入到 DownloadManager 中即可。

如此就完成了对 flutter_download_manager 的网络库扩展改造,实现了一个可定制化的网络框架的下载库。

完整源码传送门

总结

做开闭原则前,最重要的是以最小实现模型为基础捋清楚代码中的变与不变。

太棒了!鼓励自己坚持到底。我希望我为你投入的时间增加了一些价值。

如果觉得文章对你有帮助,点赞、收藏、关注、评论,一键四连支持,你的支持就是我创作最大的动力。

️ 本文由 听蝉 原创,欢迎关注公众号:编程黑板报 原创技术文章第一时间推送。 ️

最新文章

  1. hadoop-2.7.1伪分布环境搭建
  2. Toad各版本所包含的组件
  3. 原生Ajax 和Jq Ajax
  4. [原创] Linux下几种文件传输命令 sz rz sftp scp介绍
  5. 将HTML5封装成android应用APK文件的几种方法(转)
  6. Careercup - Google面试题 - 5727310284062720
  7. ActiveMQ可靠性机制
  8. Oracle中查询各种对象的方法小结
  9. [置顶] 程序员面试之道(《程序员面试笔试宝典》)之看着别人手拿大把的offer,不淡定了怎么办?
  10. Python+Selenium使用Page Object实现页面自动化测试
  11. 分享一小坑(与swagger有关),以后碰到了可以快速规避
  12. OpenCV3.1.0中调用MHI(Motion History Images, 运动历史图像)
  13. spring-cloud-hystrix-dasboard服务调用监控
  14. Linux 端口信息查看
  15. Spring MVC 中的 forward redirect Flash属性
  16. centos 7 安装svn客户端
  17. Linux 目录说解
  18. scala 几个函数小例子
  19. java SE :标准输入/输出
  20. python 笔记2016

热门文章

  1. 解决aspnetcore-browser-refresh.js:234 WebSocket connection to 'wss://localhost:62356/Admin/' failed问题
  2. Vue DevUI v1.4 版本发布:从体验、效率、质量三个方面做了全方位的优化🎉
  3. JavaScript:立即执行函数
  4. JavaScript:对象:对象和属性的内存结构是什么样的?
  5. JavaScript:输入语法:prompt与confirm
  6. [机器学习] 特征选择笔记4-使用SelectFromModel特征选择
  7. python之路39 前端开始 各种标签
  8. Java进阶篇——设计模式
  9. SICTF2023 web_wp
  10. Ubuntu 配置 Oh-my-zsh