因爲有使用的朋友提到 XSnow
框架信息量有點大,但願能有篇文章詳細介紹框架中每一個模塊的細節,因此本文會圍繞該框架將每個模塊的相關構思和重要技術點作一個詳細的剖析,讓使用該框架的朋友對 XSnow
有一個清晰的認識。html
因爲 XSnow
框架是基於 RxJava2
和 Retrofit2
打造的,其中也依賴瞭如網絡基礎庫 OkHttp
、圖片加載庫 Glide
、數據庫基礎庫 GreenDao
,因此使用該項目的朋友須要對這幾個基礎框架有基本的認識,下面將對這幾個框架作一個簡單的說明。java
熟悉的朋友可能知道該框架是屬於 ReactiveX
編程庫的一員,這是一種新的編程思想,通常都把它叫作響應式編程思想,對於使用該思想的優點在這裏就不贅述了,感興趣的朋友能夠看看這篇文章 ReactiveX 文檔中文翻譯。git
RxJava
主要的模式就是觀察者模式,何爲觀察者模式,能夠簡單的理解爲:兩個對象觀察者與被觀察者,其中觀察者與被觀察者創建了訂閱關係,若是被觀察者發生了變化那麼須要及時通知觀察者,觀察者收到通知後作出相應的處理。描述可能會有點繞,舉個通俗易懂的例子吧,好比說:顧客去買蛋糕這樣一個場景(把顧客和蛋糕店店員分別看作觀察者與被觀察者),因爲蛋糕是現作須要必定時間才能完成,顧客在購買時通常會先付錢給店員拿到一個付款憑證後離開去忙其餘事,這樣他們就創建了購買關係(創建訂閱關係),店員在作完蛋糕後(被觀察者發生變化),店員就會通知顧客來拿(消息通知到觀察者),顧客在收到店員通知後前來拿蛋糕(觀察者收到通知後作出相應的處理)。到這裏,一個完整的觀察者模式場景就講解完畢,但願能幫助朋友們加深對觀察者模式的理解。github
下面繼續講解對 RxJava
的理解,先想象一個這樣的場景,有一臺萬能機器,它能夠生產任何東西,它有一個輸入端、一個輸出端,中間有不少核心組件,好比說轉換器、轉移器等,它們對外部都是隱藏的,可是外部有一個控制終端,能夠輸入任何想要的規則,機器就會根據規則,將輸入端的東西經過終端制定的規則輸送到輸出端。RxJava
就是這樣一臺萬能機器,它擁有數據輸入端、數據輸出端,中間也有不少能夠操控數據的規則,好比說各類操做符、線程轉換,它們都有一個目的,就是如何讓數據源經過必定規則進行輸出。算法
以上的講解只是爲了讓你對 RxJava
有一個清晰的認識,不牽扯具體的技術細節,若是想詳細瞭解的能夠去看看給初學者的 RxJava2.0 教程,這是一個系列,看完這些文章,基本就可使用 RxJava
作一些基礎的功能了,這個系列是針對 RxJava2
的,若是想了解 RxJava
初版,想看看兩個版本到底發生了什麼改變,那麼能夠看看給 Android 開發者的 RxJava 詳解以及 RxJava2 vs RxJava1.數據庫
Retrofit
簡單來講就是一個基於 OkHttp
的 RESTful API
請求工具。RESTful
是一種架構風格,它的特色是資源、統一接口、URI
和無狀態,若是想更詳細的瞭解 RESTful
能夠看看RESTful 架構風格概述。編程
Retrofit
在使用時其實就充當了一個適配器(Adapter
)的角色,主要是將一個 Java
接口翻譯成一個 HTTP
請求對象,而後用 OkHttp
去發送這個請求。其中核心思想就是動態代理機制,什麼是動態代理,就是當你要調用某個 Class
的方法前或後,插入你想要執行的代碼。通俗來說,就是你要執行某個操做的先後須要增長一些操做,好比查看用戶我的信息前須要判斷用戶是否登陸,用戶訪問數據庫後想清除用戶的訪問記錄等操做。api
Retrofit
的設計很是插件化且輕量級,高內聚且低耦合。Retrofit
主要定義了 4 個接口:數組
Callback<T>
:請求數據的返回;Converter<F, T>
:對返回數據進行解析,通常用 GSON
;Call<T>
:發送請求,Retrofit
默認的實現是 OkHttpCall<T>
,也能夠依需自定義 Call<T>
;CallAdapter<T>
:將 Call
對象轉換成其餘對象,如轉換成支持 RxJava
的 Observable
對象。Retrofit
進行網絡請求的過程:緩存
Retrofit
對象和 Method
對象獲取 callAdapter
、responseType
以及 responseConverter
三個對象;Method
中的註解以及進行一系列的檢查獲得中心管理對象 ServiceMethod
;ServiceMethod
對象獲取實際執行的 Call
對象執行 Http
請求。以上講解只是對 Retrofit
的核心功能作了相關的解釋,若是想更詳細的瞭解 Retrofit
能夠看看拆輪子系列:拆 Retrofit
OkHttp
是一個高效的 HTTP
庫,它的整體設計圖以下(圖片來源:泡在網上的日子):
OkHttp
的請求由 OkHttpClient
統一管理,採用的是門面模式,OkHttpClient
擁有子模塊的全部配置和參數,並將請求分發到相應的子系統。它由如下幾個核心子系統組成:路由、鏈接協議、攔截器、代理、安全性認證、鏈接池以及網絡適配。主要是經過 Dispatcher
不斷從 RequestQueue
中取出請求(Call
),根據是否已緩存調用 Cache
或 Network
這兩類數據來獲取某個接口,再從內存緩存或是服務器取得請求的數據。該引擎有同步和異步請求,同步請求經過Call.execute()
直接返回當前的 Response
,而異步請求會把當前的請求(AsyncCall
)Call.enqueue
添加到請求隊列中,並經過回調(Callback
)的方式來獲取最後結果。
OkHttp
中的 Interceptor
(攔截器)方式對於總體的設計提供了很大的幫助,它採用的是責任鏈模式,它不僅是負責攔截請求進行一些額外的處理(例如增長請求頭),實際上它把實際的網絡請求、緩存、透明壓縮等功能都統一了起來,每個功能都只是一個 Interceptor
,它們再鏈接成一個 Interceptor.Chain
,環環相扣,最終圓滿完成一次網絡請求。
以上講解只是對 OkHttp
的流程作了相關的解釋,若是想更詳細的瞭解 OkHttp
能夠看看拆輪子系列:拆 OkHttp。
Glide
是爲圖片加載而生,一行代碼Glide.with(this).load(url).into(imageView);
就搞定圖片的加載。使用很是簡單,若是想詳細瞭解的,這裏推薦郭霖的 Glide 源碼解析,Android 圖片加載框架最全解析,這是一個系列,看完後對於 Glide 基本就能知道怎麼用和爲啥要這樣用了。
GreenDao
是一個將對象映射到 SQLite
數據庫中的輕量且快速的 ORM
解決方案。若是想更詳細的瞭解 GreenDao
能夠看看Android 數據存儲之 GreenDao 3.0 詳解。
XSnow
框架利用的相關技術有個直觀的感覺,若是想詳細瞭解的,上面在每一個基礎庫後面都備註了我的認爲比較好的文章,能夠當作學習該框架的參考。該模塊是 XSnow
框架的核心功能,其核心思想就是將請求分離和基於動態配置,採用門面模式,上層不用關係具體實現細節,只須要簡單配置相關的請求信息就能夠達到完整的網絡請求功能。該模塊相對於其餘模塊代碼量比較大,下面將會對該模塊下的每個包進行詳細拆分講解,如今咱們首先來看看 ViseHttp
類,該類至關於該模塊的門面類,也是網絡請求的惟一入口類,全部的請求都是由該類構建,如:
GET
方式請求對象;POST
方式請求對象;HEAD
方式請求對象;PUT
方式請求對象;PATCH
方式請求對象;OPTIONS
方式請求對象;DELETE
方式請求對象;該類還提供了根據 tag
中斷單個網絡請求以及中斷全部網絡請求功能,也提供了根據 key
刪除緩存和清除全部網絡緩存功能。必須注意的是,在應用初始化時必須調用該類的初始化方法
ViseHttp.init(this);複製代碼
以及相關的網絡配置
ViseHttp.CONFIG()
//配置請求主機地址
.baseUrl("http://10.8.4.39/")
//配置全局請求頭
.globalHeaders(new HashMap<String, String>())
//配置全局請求參數
.globalParams(new HashMap<String, String>())
//配置讀取超時時間,單位秒
.readTimeout(30)
//配置寫入超時時間,單位秒
.writeTimeout(30)
//配置鏈接超時時間,單位秒
.connectTimeout(30)
//配置請求失敗重試次數
.retryCount(3)
//配置請求失敗重試間隔時間,單位毫秒
.retryDelayMillis(1000)
......;複製代碼
這樣才能在應用中調用相關的網絡請求功能。若是沒有初始化,在調用網絡請求時該模塊會拋出以下異常信息:
Please call ViseHttp.init(this) in Application to initialize!複製代碼
切記!
下面來分別講解該模塊下每一個包的功能:
api
該包提供的是請求的 API
,目前只有一個類 ApiService
,主要提供的是 Retrofit
進行網絡請求的請求方法。
body
該包提供的是相關的請求和響應 body
,目前只有一個上傳進度展現的請求實體類 UploadProgressRequestBody
,經過傳入 UCallback
來處理上傳文件的進度回調。
callback
該包提供的是相關的回調類,目前包含上傳回調 UCallback
和請求 API
回調 ACallback
。
config
該包提供的是配置相關類,目前只有請求全局配置類 HttpGlobalConfig
,該類提供了很豐富的配置方法,提供該類的目的是想將配置與請求分離。
core
該包提供的是一些核心功能類,目前包含緩存處理類 ApiCache
、Cookie
管理類 ApiCookie
以及網絡請求訂閱管理類 ApiManager
。緩存採用磁盤緩存方式,支持定製各類緩存策略,策略將在 strategy
包下進行講解。Cookie
採用 SharedPreferences
存儲,存儲對象以十六進制進行保存。
exception
該包提供網絡請求相關異常類,目前提供了請求異常統一處理類 ApiException
,可用來斷定請求失敗的緣由。
func
該包提供一些數據轉換類,目前提供了由 ResponseBody
對象轉 T
的 ApiFunc<T>
類以及由 Observable<? extends Throwable>
轉 Observable<?>
的 ApiRetryFunc
類。ApiRetryFunc
類主要用來處理網絡超時重試機制,可傳入重試次數和重試間隔時間,這些均可以在配置類中進行配置。
interceptor
該包提供的是一系列的攔截器類,這個包也算是該模塊的核心包,基本大部分功能均可以採用攔截器的方式來提供,目前該包下面包含以下攔截器:
一、GzipRequestInterceptor
:包含Gzip壓縮的請求攔截;
二、HeadersInterceptor
:請求頭攔截;
三、HttpLogInterceptor
:Http日誌打印攔截;
四、NoCacheInterceptor
:無緩存攔截;
五、OfflineCacheInterceptor
:離線緩存攔截;
六、OnlineCacheInterceptor
:在線緩存攔截;
七、UploadProgressInterceptor
:上傳文件進度展現攔截。
mode
該包提供的是相關的實體類。
request
該包提供的是全部請求相關的類,全部的網絡請求都須要建立一個請求對象,該包提供了一個基礎請求類 BaseRequest<R extends BaseRequest>
,該類需將 R
寫成實際請求類,這樣才能獲取對應請求類的對象來進行相關的請求信息配置,若是請求配置與全局配置衝突,那麼優先請求配置,意思就是局部請求配置會替換掉相同的全局配置。
請求類中提供了一系列請求頭配置、請求參數配置等信息,若是是 POST
請求還提供了上傳 JSON
字符串、上傳表單等方式,而若是是上傳文件則提供了添加文件、添加字節數組和添加流的方式。
因爲帶緩存請求和不帶緩存請求返回的結果不同,因此須要分開處理,故有 cacheExecute
和 execute
的區分。
strategy
該包提供的是緩存相關的策略,包含以下幾種策略:
一、CacheAndRemoteStrategy
:先加載緩存數據後加載網絡數據;
二、FirstCacheStrategy
:優先加載緩存數據;
三、FirstRemoteStrategy
:優先加載網絡數據;
四、OnlyCacheStrategy
:只加載緩存數據;
五、OnlyRemoteStrategy
:只加載網絡數據。
緩存策略採用面向接口編程原則,定義了一個緩存策略接口 ICacheStrategy<T>
,並將具體的策略實現交由各個子類。
subscriber
該包提供的是相關的訂閱者,目前包含 API
請求的統一訂閱者 ApiSubscriber<T>
、包含回調的訂閱者 ApiCallbackSubscriber<T>
以及包含下載回調的訂閱者 DownCallbackSubscriber<T>
。
該模塊提供了幾種緩存方式,分別是內存緩存、磁盤緩存以及 SharedPreferences
存儲。該模塊主要思想是面向接口編程,提供了 ICache
接口,主要包含添加緩存、獲取緩存、刪除緩存、清除全部緩存以及判斷是否包含該緩存這幾個能力。下面將對每一個緩存方式作詳細的解釋說明:
LruCache
,緩存算法採用 Lru
算法(Least Recently Used
近期最少使用算法),緩存大小爲最大內存的八分之一。KEY
採用 MD5
加密,可定製緩存時長,沒有定製則默認永久存儲,緩存對象爲 DiskLruCache
,緩存算法也是 Lru
算法,緩存位置和緩存大小均可以定製,若是沒有定製就會使用默認值,默認的緩存位置爲該應用緩存目錄下的 disk_cache
目錄,優先存儲到 SD
卡中,默認的緩存大小爲 20M
。SharedPreferences
存儲對緩存對象進行 Base64
加密存儲,可定製緩存文件名,若是沒有定製則使用默認文件名 sp_cache
。該模塊使用 Rx
思想實現了 RxBus
功能,其 Bus
的設計思想與 EventBus
相似。其主要由如下幾個核心類組成:
Map
以及普通事件 Subject
,也定義了獲取 Flowable
以及刪除粘性事件和刪除粘性事件 Map
的方法。EventSubscriber
,最後組合到一塊兒獲得 EventComposite
。getScheduler(ThreadMode thread)
來獲取線程調度者。事件接收採用註解方式類進行管理,事件訂閱後依據註解來查找對應的事件接收地。
該模塊爲了能將事件總線統一,定義了 IBus
接口,提供了以下四個方法:
void register(Object object);
void unregister(Object object);
void post(IEvent event);
void postSticky(IEvent event);複製代碼
也提供了 IEvent
接口,全部事件都實現該接口,這樣就能夠將具體的事件實現類抽離,其實也是面向接口編程。
該模塊也提供了插件化思想,上層能夠將如 EventBus
的實現類注入該模塊,那麼事件的處理就會採用 EventBus
實現的策略,但這裏有一個問題,因爲事件接收採用的是註解方式,而 EventBus
中的註解是不一樣的,因此仍是須要把註解事件進行統一替換,耦合性過高,目前沒有發現更好的方式,若是哪位朋友有好的去耦合方式,歡迎留言交流!
該模塊針對圖片加載作了二次封裝,面向接口編程,每一個實現就是一種圖片加載策略,默認採用 Glide
圖片加載框架,上層也能夠依需自定義實現接口 ILoader
,好比 Demo
中提供的 Fresco
圖片框架的實現類 FrescoLoader
,其主要思想就是插件化,外部可注入任何加載策略,這樣可達到高內聚低耦合。
接口中提供了以下四種加載圖片的方式:
void loadNet(ImageView target, String url, Options options);複製代碼
void loadResource(ImageView target, int resId, Options options);複製代碼
void loadAssets(ImageView target, String assetName, Options options);複製代碼
void loadFile(ImageView target, File file, Options options);複製代碼
默認的 Glide
框架採用 provided
方式依賴,這樣就只是編譯時依賴,運行時不依賴,上層若是肯定使用 GlideLoader
加載策略,那麼還須要本身使用 compile
進行依賴,這樣運行時纔不會報錯,GlideLoader
在初始化時也增長了以下驗證機制
try {
Class.forName("com.bumptech.glide.Glide");
} catch (ClassNotFoundException e) {
throw new IllegalStateException("Must be dependencies Glide!");
}複製代碼
若是沒有依賴 Glide
庫則會拋出異常。
該模塊將 GreenDao
做爲底層數據庫,定義了數據庫的操做接口 IDatabase<M, K>
,統一由 DBManager<M, K>
抽象類管理,因爲每一個實體類對應的 Dao
不同,因此定義了抽象方法 getAbstractDao()
。因爲 GreenDao
的特殊性,該方法的實現類不能在框架中搭建,全部數據庫操做均可以參考 Demo
中 DbHeDlper
類實現本身的數據庫操做管理類,不一樣的 Dao
實現對應的 getAbstractDao()
方法就行。
該模塊利用 Rx
思想統一管理權限的申請,一行代碼搞定權限的申請問題。
PermissionManager.instance().with(this).request(onPermissionCallback, Manifest.permission.CALL_PHONE);複製代碼
該模塊很簡潔,就幾個類,下面分別對它們進行介紹:
PermissionManager:權限管理類,也是權限申請的惟一入口,採用單例模式,須要經過 with
將當前的 Activity
對象傳進去,調用 request
方法就能夠進行權限申請,須要傳入回調和權限列表,權限列表採用可變數組方式傳入,使用示例以下:
PermissionManager.instance().with(this).request(new OnPermissionCallback() {
@Override
public void onRequestAllow(String permissionName) {
DialogUtil.showTips(mContext, getString(R.string.permission_control),
getString(R.string.permission_allow) + "\n" + permissionName);
}
@Override
public void onRequestRefuse(String permissionName) {
DialogUtil.showTips(mContext, getString(R.string.permission_control),
getString(R.string.permission_refuse) + "\n" + permissionName);
}
@Override
public void onRequestNoAsk(String permissionName) {
DialogUtil.showTips(mContext, getString(R.string.permission_control),
getString(R.string.permission_noAsk) + "\n" + permissionName);
}
}, Manifest.permission.CALL_PHONE);複製代碼
Activity
獲取一個 Fragment
來進行權限申請回調處理,提供了一系列權限申請的方法,有多個權限單獨處理回調和統一處理回調的方式,分別是 requestEach
和 request
方式。Fragment
。該模塊包含萬能適配器和試圖切換功能。適配器部分採用 ViewHolder
來管理數據的裝載和展現,將數據與展現分離,提供了 DataHelper
接口來裝載數據,ViewHelper
接口來處理 UI
的展現。其中的 HelperAdapter
提供了適配器的經常使用方法,基本能知足適配器的經常使用需求。
視圖切換部分由 StatusLayoutManager
統一管理,經過傳入相關配置進行視圖展現處理。內部提供了 OnRetryListener
重試監聽和 OnStatusViewListener
試圖切換監聽,並定義了一個自定義視圖 StatusLayout
用來展現如下五種視圖:
到此,XSnow
框架的全部模塊就介紹完畢了,不知各位朋友是否對該框架有了更深刻的瞭解。
以上描述有些部分可能講解比較簡單,這是由於有些模塊自己不是很複雜,因此就沒有作過多的講解,若是想更清晰的瞭解該框架,最好的辦法是直接 down
下源碼觀察,若是在看源碼過程當中有哪裏不理解或以爲實現有問題而你有更好的方案均可以留言交流!
源碼地址:github.com/xiaoyaoyou1…,源碼地址中提供了詳細的使用文檔,裏面有版本介紹以及QQ羣等信息,若是喜歡該框架不妨點點 star
並分享給身邊的朋友,讓更多的朋友參與進來,謝謝你們!