如何對 Android 庫進行依賴管理?
Android 開發人員為專案選擇庫的時候,考慮的因素不僅僅是功能、可用性、效能、文件豐富度和技術支援情況。他們還關心庫的大小,以及要新增的方法數量。因為專案越大,依賴也越多,要把應用的方法數量控制在65k 以下,開發人員感覺很有壓力。另外,對於非發行版專案而言,Proguard 使用起來效率太低,而且開發人員視 multidex 如瘟疫,避之唯恐不及。因此,編寫庫的作者必須特別注意專案的大小。
為了減少庫的方法數量,最簡單的途徑就是不包含任何多餘的依賴。因為你包含的所有依賴,都會被傳遞並新增至使用者的專案裡。舉個例子,如果你只需要幾個簡單的工具方法,比如默默地關閉一個資源,那就沒必要為此新增 [Guava](https://github.com/google/guava 「Guava」 )。自己編寫方法,或者從一個現有的庫中提取(但是務必做出說明)就可以了。使用者肯定會感激你去除了多餘的14k方法。
但是,這並不是說你不該使用外部庫,而是你要做出明智的選擇。比如,像 HTTP 客戶端這樣的庫已經有了,你若再去重寫一個,最終結果只能是浪費時間,倒不如用這些時間改進自己的庫。
除了有選擇地使用庫以外,還有幾個策略也可以幫助你保持庫的精簡。其中一個策略就是使用 provided scope(已提供範圍)來宣告依賴。 這是 gradle 中 Android build system(Android 構建系統)的一部分。與 compile scope(編譯範圍)不同,provided scope 僅在編譯時包含依賴。這就意味著,使用者在構建專案時,該依賴不會隨著 APK 檔案打包。如果想在執行時使用該依賴,使用者需要在應用的 build.gradle 裡顯式宣告。
注意: 還有一種與 provided scope 相反的機制叫 package scope(包範圍)。這種依賴會隨 APK 檔案打包,但是在編譯時不可用。
你可能還想在庫中使用可選擇性依賴。其中一個原因是,某些功能可能只有部分使用者使用。例如 [Retrofit 1.x](https://github.com/square/retrofit/tree/version-one 「Retrofit 1.x」 ),該庫可以使用 REST 呼叫來響應,而不使用回撥。那些想使用 RxJava 的使用者可以新增之,而不想使用它的使用者也可以不新增,以免加重負擔。自從 Retrofit 使用 maven build system(maven 構建系統)以後,其配置稍有更改,但理念還是相似的。
在此筆者要提醒大家,如果你發現自己庫中的某些功能只對少數使用者有用,你應該認真考慮一下是否還要保留這些功能。關於這一點,後文中還會講到。
在庫裡包含可選擇性依賴的另一個原因,是Android 框架已經提供了一種解決方案,但是某個外部庫提供的解決方案效能更好。如果使用者本就依賴於該外部庫,或者願意增加方法數量以獲得更好的效能,就可以新增可選擇性依賴。
我最近看到的PlacesAutocompleteTextView庫,就屬於這種情況。該庫使用的內部 HTTP 客戶端,既可以是 OkHttpClient,也可以是 HttpURLConnection。通常,前者的效能更好,但是需要新增 OkHttp 作為依賴。 如果使用者不想包含該依賴,可以自動從標準庫回退到 HttpURLConnection。
為此,需要一個「resolver」 類以確定執行時要使用的依賴。 例如,以下的類就用於選擇 HTTP 客戶端:
public final class PlacesHttpClientResolver {
public static final PlacesHttpClient PLACES_HTTP_CLIENT;
static {
boolean hasOkHttp;
try {
Class.forName("com.squareup.okhttp.OkHttpClient");
hasOkHttp = true;
} catch (ClassNotFoundException e) {
hasOkHttp = false;
}
PlacesApiJsonParser parser = JsonParserResolver.JSON_PARSER;
PLACES_HTTP_CLIENT = hasOkHttp ? new OkHttpPlacesHttpClient(parser) : new HttpUrlConnectionMapsHttpClient(parser);
}
private PlacesHttpClientResolver() {
throw new RuntimeException("No Instances!");
}
}
該類被載入時,會檢查 OkHttpClient 的完全限定類名是否可用。如果丟擲 ClassNotFoundException,我們就知道使用者沒有新增 OkHttp,於是回退到 HttpURLConnection。PlacesHttpClient 是包裝以上兩種實現方式的公共介面,因此在整個程式碼庫中,這兩種實現方式可以交換使用。JSON 解析也採用了同樣的方法,Gson 可選擇性地作為依賴包含在庫中。
如果效能表現與庫的大小之間的權衡係數很大,這個方法確實不錯。但是,如果回退的實現方式比較困難(比如 JSON 解析就是這種情況),筆者建議你先使用外部庫來節省時間,在後續的版本中再考慮新增回退實現。
筆者在前文中提到,你應該對庫中包含的功能做出明智的選擇。如果某個功能幾乎所有使用者都不需要,最好將其除去,而且這裡也沒有必要使用前面提到的第一種可選擇性依賴。再次以 Retrofit 為例,在 2.x 版本 中,使用 REST 呼叫來響應這個功能,不再作為核心庫的一部分提供給使用者,而是移到一個單獨的模組上,並作為 Retrofit 的 maven 構件釋出 。
同樣地,不同的響應轉換器也被拆成了獨立的依賴。例如,Retrofit 使用者想要轉換一個 JSON 響應,而且已經依賴於 Gson,他們可以在 build.gradle 檔案中新增以下依賴:
dependencies {
compile 'com.squareup.retrofit:converter-gson:2.0.0-beta2'
}
而那些使用其他 JSON 庫(比如 Jackson)的使用者,或者需要解析其他資料格式(比如 XML 或 protocol buffers)的使用者,也可以採用這種方式新增自己需要的依賴,而且避免通用型依賴帶來的額外負擔。與此同時,核心庫也不會被這些附加功能干擾,可以專注於需要解決的主要問題。
總而言之,如果你正在編寫的庫有意給 Android 開發人員使用,在設計時務必記住以上幾個策略。庫的大小,不應該只當做屬性,而應該視為一種特性予以考慮,你的使用者絕對會因此而感激你!
OneAPM Mobile Insight 以真實使用者體驗為度量標準進行 Crash 分析,監控網路請求及網路錯誤,提升使用者留存。訪問 OneAPM 官方網站感受更多應用效能優化體驗,想閱讀更多技術文章,請訪問 OneAPM 官方技術部落格。
本文轉自 OneAPM 官方部落格
原文地址:http://johnpetitto.com/android-lib-dependency-management/
相關文章
- Android 依賴管理簡介Android
- 依賴管理和依賴範圍
- npm如何管理依賴包的版本NPM
- Android studio 匯入依賴庫Android
- golang 依賴管理Golang
- Maven依賴管理:控制依賴的傳遞Maven
- 利用 uber-go/dig 庫管理依賴Go
- govendor依賴包管理Go
- Gradle for Android系列之四 依賴包管理GradleAndroid
- Gradle for Android 第三篇( 依賴管理 )GradleAndroid
- 如何發現Python依賴庫漏洞Python
- 如何建立依賴專案工程--android moduleAndroid
- 探索 JavaScript 中的依賴管理及迴圈依賴JavaScript
- 依賴引入 | Android依賴引入史上最全攻略Android
- android引入依賴,合集Android
- PHP依賴管理ComposerPHP
- Flutter 中的依賴管理Flutter
- Maven依賴管理系統Maven
- 專案管理中,如何識別和管理依賴關係?專案管理
- Android開發好用的依賴庫和工具收集Android
- 不要依賴Mock庫 - ErwinMock
- Android 依賴注入框架RoboGuiceAndroid依賴注入框架GUI
- 依賴注入?依賴注入是如何實現解耦的?依賴注入解耦
- nodejs 中的依賴管理NodeJS
- 開源依賴項管理指南
- PHP之依賴管理composerPHP
- Maven最佳實踐:管理依賴Maven
- Android下檢視SO庫被依賴的情況Android
- Gradle For Android (一) 基礎定義與依賴管理篇GradleAndroid
- 用Gradle 構建你的android程式-依賴管理篇GradleAndroid
- 在控制檯進行依賴注入(DI in Console)依賴注入
- saltstack對遞迴依賴條件(死迴圈依賴)的處理遞迴
- Maven中如何管理多模組專案的依賴關係Maven
- 如何管理前端專案中的複雜依賴關係前端
- 使用godep管理Golang專案依賴Golang
- Composer -- PHP依賴管理的用法PHP
- 使用govendor管理Golang專案依賴Golang
- 官方依賴管理工具:dep