网易考拉Android客户端网络模块设计
本文來自網(wǎng)易云社區(qū)
作者:王魯才
客戶端開發(fā)中不可避免的需要接觸到訪問網(wǎng)絡的需求,如何把訪問網(wǎng)絡模塊設(shè)計的更具有擴展性是每一個移動開發(fā)者不得不面對的事情。現(xiàn)在有很多主流的網(wǎng)絡請求處理框架,如Square公司的OkHttp,Google推出的Volley,還有在OkHttp基礎(chǔ)上進行封裝的Retrofit等,這些都是非常優(yōu)秀的網(wǎng)絡處理框架。利用現(xiàn)有網(wǎng)絡處理框架,比從零開始設(shè)計、開發(fā)網(wǎng)絡請求節(jié)省很多開發(fā)時間,同時也避免了一些意想不到的問題。如果把這些框架直接拿來使用,不進行任何二次封裝,會使我們工程層次結(jié)構(gòu)不清晰(數(shù)據(jù)存取、邏輯處理、UI展示),不利于擴展(替換成其他網(wǎng)絡框架)。所以選擇一個合適的網(wǎng)絡框架并進行封裝,這在開發(fā)過程中是非常必要的。
1. 概述
通常情況下,客戶端數(shù)據(jù)流遵循如下圖所述方式流動,UI層負責展示數(shù)據(jù),接收用戶操作;邏輯處理層處理用戶操作,并將處理結(jié)果反饋給UI層進行展示;數(shù)據(jù)層負責數(shù)據(jù)存取,這里可能會涉及多種方式存取數(shù)據(jù):本地緩存中存取數(shù)據(jù),向服務器請求存取數(shù)據(jù);網(wǎng)絡訪問層負責從服務器存取數(shù)據(jù),數(shù)據(jù)返回后進行解析,并將結(jié)果返回給數(shù)據(jù)存取層。
2. 考拉Android客戶端網(wǎng)絡模塊設(shè)計
下面簡要介紹一下考拉Android客戶端網(wǎng)絡模塊設(shè)計的變遷歷程,在這個過程中我們也踩了不少坑,好在我們把這些坑都填平了,而且正在朝著更好的方向發(fā)展。
在考拉項目開始之初,我們對比了Volley、OKHttp等主流網(wǎng)絡處理框架,最終選擇了Volley作為考拉Android客戶端的網(wǎng)絡請求模塊。Volley是在2013年IO大會上Google推出的異步網(wǎng)絡請求框架(和圖片加載框架),特別適合數(shù)據(jù)量小,通信頻繁的網(wǎng)絡操作。
2.1 存在的問題
1. 封裝擴展性差(SPDY,HTTPS);
2. 存在內(nèi)存泄漏(Volley自己的問題);
3. 數(shù)據(jù)解析在UI線程中進行,阻塞UI展示;
在這一版本的網(wǎng)絡請求封裝中存在一個比較嚴重的問題,數(shù)據(jù)解析在UI線程中進行,在最初的幾個版本中,請求的數(shù)據(jù)量較小,UI比較簡單,阻塞UI線程的這個問題還不是特別明顯,但是隨著UI越來越復雜,同時請求數(shù)據(jù)、解析數(shù)據(jù)的操作也越來越多,阻塞UI線程解析數(shù)據(jù),存在丟幀問題。為了解決這個問題,引入了工作線程池,網(wǎng)絡請求回來以后,先將數(shù)據(jù)返回給調(diào)用者(UI線程),調(diào)用者在解析數(shù)據(jù)的時候,開啟工作線程,數(shù)據(jù)解析完成后再拋回UI線程,UI線程進行數(shù)據(jù)展示。在這個過程中,有多次線程切換,線程創(chuàng)建、切換、調(diào)度都是需要內(nèi)存、時間開銷的。更要命的是,這個過程對調(diào)用者不透明,調(diào)用者必須知道當前操作是在哪個線程中進行的。
擴展性差這一點相信很多開發(fā)者都有比較痛的感悟。為了兼容不同服務器返回的不同數(shù)據(jù)格式,在網(wǎng)絡請求模塊中定義了很多不同參數(shù)的回調(diào)方法。在請求數(shù)據(jù)時,每一種回調(diào)接口都要對應一個具體的方法(傳入的回調(diào)接口不同),代碼寫的比較冗余,條理性、擴展性差,簡直要不能直視了。
2.2 重構(gòu)
為了解決上面兩個問題,對網(wǎng)絡請求模塊進行了重構(gòu),引入了泛型數(shù)據(jù),重新定義了網(wǎng)絡數(shù)據(jù)返回結(jié)構(gòu),新增了數(shù)據(jù)解析器。根據(jù)用戶傳入的不同解析器,將網(wǎng)絡返回數(shù)據(jù)解析成不同類型。在網(wǎng)絡數(shù)據(jù)返回后,直接將數(shù)據(jù)解析操作從UI線程中拋到工作線程中,這個過程對調(diào)用者是透明的。調(diào)用者只需要知道網(wǎng)絡請求操作和數(shù)據(jù)解析操作是在工作線程中進行的,回調(diào)接口在UI線程中執(zhí)行就可以。
在這個網(wǎng)絡響應回調(diào)接口中,采用了泛型,調(diào)用者可以返回任意數(shù)據(jù)結(jié)構(gòu),為了提高兼容性,在錯誤回調(diào)方法中,不僅傳入了錯誤碼和錯誤原因,而且還額外增加了一個Object類型的數(shù)據(jù),供調(diào)用者返回其他數(shù)據(jù)信息。
KoalaStringParser是通用數(shù)據(jù)解析接口,主要針對有特殊需求的數(shù)據(jù)解析;對于通用的、與服務器約定好的數(shù)據(jù)返回格式,可以繼承KoalaSimpleStringParser抽象類,實現(xiàn)onSimpleParse抽象方法解析數(shù)據(jù)。通用數(shù)據(jù)解析接口和抽象數(shù)據(jù)解析類,既保證了擴展性,又對通用數(shù)據(jù)格式有了統(tǒng)一處理。
2.3 數(shù)據(jù)緩存
如果不考慮數(shù)據(jù)緩存的話,上面對網(wǎng)絡請求的封裝基本也能滿足我們的要求了。但是如果沒有數(shù)據(jù)緩存,每次都向服務器請求數(shù)據(jù),啟動新頁面,會有時間長短不一的加載過程,沒有網(wǎng)絡或者網(wǎng)絡不好時,會顯示一個空白頁面告訴用戶網(wǎng)絡不可用,這降低了用戶體驗。為了提升用戶體驗,減少啟動頁面的等待時間,增加數(shù)據(jù)緩存是一件很有必要的事情。緩存可以與服務器配合,使用HTTP的緩存機制,也可以在客戶端單獨使用。因為現(xiàn)在考拉服務器還沒有支持緩存,現(xiàn)階段只能在客戶端添加緩存。
上面是在沒有服務器支持的情況下,客戶端支持的緩存。在啟動頁面請求數(shù)據(jù)時,先判斷是否允許讀取緩存數(shù)據(jù)。允許讀取緩存數(shù)據(jù),檢查是否存在緩存數(shù)據(jù),存在緩存數(shù)據(jù),將數(shù)據(jù)從本地緩存中讀取后直接返回給調(diào)用者;不存在緩存數(shù)據(jù),不做任何處理。在檢查緩存數(shù)據(jù)時,同時向服務器發(fā)送請求,獲取數(shù)據(jù),數(shù)據(jù)返回后更新緩存數(shù)據(jù)。這里需要注意的是,回調(diào)接口可能會被調(diào)用兩次,一次是從緩存讀取數(shù)據(jù)的回調(diào),一次是從服務器讀取數(shù)據(jù)的回調(diào)。出現(xiàn)兩次回調(diào)的問題,需要調(diào)用者進行區(qū)分,在回調(diào)方法中添加了當前回調(diào)是從本地讀取數(shù)據(jù)的回調(diào)還是從網(wǎng)絡讀取數(shù)據(jù)的回調(diào)標示。
服務端不支持緩存,只在客戶端對數(shù)據(jù)進行緩存處理,在一定程度上提升了用戶體驗,避免用戶多次請求相同頁面時出現(xiàn)多次重復加載、長時間等待的問題。這種緩存方式并不能節(jié)省用戶流量。
2.4 切換到OkHttp
前一段時間項目組提到考拉可能會引入SPDY來優(yōu)化性能,后面為了解決劫持問題,還可能會上HTTPS,考慮到OkHttp已經(jīng)內(nèi)置了對SPDY的支持,而且對HTTPS的封裝比較好,未雨綢繆,我們決定從Volley轉(zhuǎn)投OkHttp了,因為之前已經(jīng)對網(wǎng)絡請求進行了封裝,所以切換到OkHttp還是比較容易的。
OkHttp具有如下優(yōu)點:
1. 支持SPDY,共享同一個Socket來處理同一個服務器的所有請求;
2. 如果SPDY不可用,則通過連接池來減少請求延時;
3. 無縫的支持GZIP來減少數(shù)據(jù)流量;
4. 緩存網(wǎng)絡數(shù)據(jù),減少重復網(wǎng)絡請求;
5. 支持HTTP2;
使用OkHttp既可以在工作線程中請求數(shù)據(jù),也可以在UI線程中請求數(shù)據(jù),這與Volley只能在工作線程中請求數(shù)據(jù)不同。在工作線程中請求數(shù)據(jù),數(shù)據(jù)返回后不需要重新開啟線程解析數(shù)據(jù),數(shù)據(jù)在請求線程中解析完后,直接拋到UI線程中進行展示。
3. 總結(jié)
在設(shè)計開發(fā)功能模塊時,往往為了快速完成功能,忽略了模塊的擴展性,當后續(xù)功能越來越復雜時,之前設(shè)計的功能、接口已經(jīng)不能滿足需求時,就要重新審視模塊是否需要重構(gòu)、優(yōu)化,不能總在舊的代碼上打補丁,造成代碼難以閱讀、維護。
4. SPDY簡介
SPDY是Google開發(fā)的基于傳輸控制協(xié)議(TCP)的應用層協(xié)議,用以最小化網(wǎng)絡延遲,提升網(wǎng)絡速度,優(yōu)化用戶的網(wǎng)絡使用體驗。SPDY并不是一種用于替代HTTP的協(xié)議,而是對HTTP協(xié)議的增強。新協(xié)議的功能包括數(shù)據(jù)流的多路復用、請求優(yōu)先級以及HTTP報頭壓縮。SPDY協(xié)議在性能方面對HTTP做了很大的優(yōu)化,語義方面并沒有做太大的修改。具體來說是,SPDY使用了HTTP的方法和頁眉,但是刪除了一些報頭并重寫了HTTP中管理連接和數(shù)據(jù)轉(zhuǎn)移格式的部分,基本上兼容HTTP。
網(wǎng)易云免費體驗館,0成本體驗20+款云產(chǎn)品!
更多網(wǎng)易研發(fā)、產(chǎn)品、運營經(jīng)驗分享請訪問網(wǎng)易云社區(qū)。
相關(guān)文章:
【推薦】 知物由學|你的網(wǎng)絡安全問題背后的真正原因
【推薦】 非對稱加密與證書(上篇)
總結(jié)
以上是生活随笔為你收集整理的网易考拉Android客户端网络模块设计的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: firefox渗透安全插件汇总
- 下一篇: [运维] linux上安装libvirt