Flutter 下載篇 - 貳 | 當下載器遇上切換網路庫

睡覺誰叫發表於2023-03-04

需求背景

繼上篇《Flutter 下載篇 - 壹 | flutter_download_manager 原始碼解析》中詳細介紹了 flutter_download_manager 用法和原理。在優缺點中提到,該庫純 Dart 實現,支援下載管理,暫停,恢復,取消和斷點續傳。其中有個缺點是網路庫與 dio 強耦合,不支援自定義網路庫擴充套件。

有人會說: dio 這麼牛逼,直接用不就好了,為啥還要支援別的網路庫,沒事別瞎折騰。

我想說:

  1. 世界不只有一種聲音,那不然多無趣。
  2. 第三方庫對應用本身來說是黑盒,開發者一般疏於關注其功能改動對應用影響除非產生重大事故,這種不可控的情況應謹慎。
  3. 設計上遵循 DIP 原則,抽象不要依賴具體實現細節,具體細節依賴抽象,我們需要抽象網路層來給專案依賴而非直接依賴 dio。
  4. 快速切換到其他網路庫。

本文將從現狀出發,一步步帶你解耦 flutter_download_manager 中的網路庫。

現狀說明

從類圖上整體瞭解 flutter_download_manager 類設計過程中對 dio 強耦合概括,然後透過程式碼具體講解。

類圖體現

Untitled.png

程式碼體現

耦合點一:dio.CancelToken

Untitled 1.png

每個下載任務請求中都會使用到 dio:CancelToken 透過 dio 網路庫間接實現任務的取消功能。

耦合點二:dio.download

cancelToken.cancel() 算依賴 CancelToken

Untitled 2.png

如上簡寫程式碼中呼叫鏈關係,最終呼叫鏈及對 dio 依賴關係總結:

下載庫對 dio 的依賴在於: CancelToken 和 download 方法

Untitled 3.png

如何定製網路庫

透過上述對現狀分析總結,結合設計基本原則:封裝變化將不變從變化中隔離出來。其中變化的就是網路庫的下載,CancelToken 和取消功能。只用封裝這部分變化,將網路庫下載和 Token 抽象出來進行封裝。

1. 網路層設計

目的:讓 flutter_download_manager 與 dio.download 解耦。

思路:將網路相關操作抽象成介面,依賴注入到 downloadManager 物件中。

實施步驟

  1. 抽象網路層介面

考慮到 download 返回 Future 中物件問題,因為會用到 response.statusCode,這裡直接用 dynamic 來,具體可以細化成封裝成 DownloadResponse,其中包含 statusCode 屬性。

Untitled 4.png

  1. customhttpclient 透過依賴注入傳入 DownloadManager,讓其不依賴具體實現而依賴抽象,依賴注入實現物件之間的組合關係提高擴充套件性。

Untitled 5.png

2. CancelToken 設計

目的:讓 flutter_download_manager 與 dio.CancelToken 解耦。

思路:CancelToken 與取訊息息相關,而且必須提供一個 cancel 方法來供 downloadmanager 中暫停等方法使用。考慮到每個 custom_http_client 的 CancelToken 結構體存在不一樣,而 cancel 方法命名多樣性原則,這裡設計一個統一的 DownloadCancelToken 介面,提供 cancel 方法,將其中實現代理給具體網路庫的 CancelToken 物件。

實施步驟

  1. 抽象一個 Token 物件並提供 cancel 方法,並實現一個預設代理其他網路庫的 Proxy 類。

小技巧: 用 Function.apply 是因為它本身支援位置引數和可選引數傳入。

Untitled 6.png

  1. custom_http_client 中抽象一個 DownloadCancelToken 抽象介面供外部使用

Untitled 7.png

3. 下載器設計

目的:下載器與具體實現 downloadmanager 解耦

思路:downloadmanager 中提供了 addDownload 等下載通用方法及下載管理邏輯抽象。這塊存在變化可以有多種實現,也抽象下。

實施步驟:

  1. 下載器抽象成介面

Untitled 8.png

  1. downloadManager 依賴 IDownloader

Untitled 9.png

至此,可定製網路庫改造已全部完成,接下來就可以隔離 dio 網路實現了。

網路庫隔離效果

Untitled 10.png

透過依賴注入到 DownloadManager 中即可。

Untitled 11.png

如此就完成了對 flutter_download_manager 的網路庫擴充套件改造,實現了一個可定製化的網路框架的下載庫。

完整原始碼傳送門

總結

做開閉原則前,最重要的是以最小實現模型為基礎捋清楚程式碼中的變與不變。

太棒了!鼓勵自己堅持到底。我希望我為你投入的時間增加了一些價值。

如果覺得文章對你有幫助,點贊、收藏、關注、評論,一鍵四連支援,你的支援就是我創作最大的動力。

❤️ 本文由 聽蟬 原創,歡迎關注公眾號:程式設計黑板報 原創技術文章第一時間推送。 ❤️

相關文章